Compare commits

..

No commits in common. "377b10cda28cef1f7362cdfdc93eba6dce490881" and "294ad3dbbd2988694cb911829f4067ec38238b96" have entirely different histories.

12 changed files with 228 additions and 847 deletions

View file

@ -1,11 +1,14 @@
use std::borrow::Cow;
use std::{
borrow::Cow,
ops::{Deref, DerefMut},
sync::Arc,
};
use ash::vk;
use gpu_allocator::vulkan::AllocationScheme;
use ash::{prelude::VkResult, vk};
use crate::{
Device,
device::{Allocation, AllocationStrategy, DeviceObject, QueueFlags},
device::{Allocation, DeviceObject, QueueFlags},
};
#[derive(Clone)]
@ -15,9 +18,7 @@ pub struct BufferDesc {
pub size: u64,
pub usage: vk::BufferUsageFlags,
pub queue_families: QueueFlags,
pub mem_location: gpu_allocator::MemoryLocation,
pub alloc_scheme: AllocationStrategy,
}
impl std::hash::Hash for BufferDesc {
@ -39,7 +40,6 @@ impl std::fmt::Debug for BufferDesc {
.field("usage", &self.usage)
.field("queue_families", &self.queue_families)
.field("mem_location", &self.mem_location)
.field("alloc_scheme", &self.alloc_scheme)
.finish()
}
}
@ -66,7 +66,6 @@ impl Default for BufferDesc {
usage: Default::default(),
queue_families: QueueFlags::empty(),
mem_location: gpu_allocator::MemoryLocation::Unknown,
alloc_scheme: AllocationStrategy::default(),
}
}
}
@ -98,12 +97,7 @@ impl Buffer {
requirements,
location: desc.mem_location,
linear: true,
allocation_scheme: match desc.alloc_scheme {
AllocationStrategy::AllocatorManaged => {
AllocationScheme::GpuAllocatorManaged
}
AllocationStrategy::Dedicated => AllocationScheme::DedicatedBuffer(buffer),
},
allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
})?;
Ok(Self {
@ -152,7 +146,7 @@ impl Buffer {
}
}
pub fn raw(&self) -> vk::Buffer {
pub fn buffer(&self) -> vk::Buffer {
*self.buffer
}
pub fn len(&self) -> u64 {

View file

@ -33,7 +33,7 @@ impl Drop for SingleUseCommandPool {
impl SingleUseCommandPool {
pub fn new(device: Device, queue: Queue) -> VkResult<Arc<Self>> {
let pool_info = vk::CommandPoolCreateInfo::default()
.queue_family_index(queue.family_index())
.queue_family_index(queue.family())
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
let pool = unsafe { device.dev().create_command_pool(&pool_info, None)? };
@ -110,7 +110,7 @@ impl<T: HasQueue> CommandList<T> {
self.0[0]
.device()
.dev()
.queue_submit(queue.raw(), &[info], fence.raw())
.queue_submit(queue, &[info], fence.fence())
})?;
Ok(FenceFuture::<'a>::new(fence))
@ -257,7 +257,7 @@ impl SingleUseCommand {
self.pool.queue().with_locked(|queue| unsafe {
self.device()
.dev()
.queue_submit(queue.raw(), &[submit_info], fence)
.queue_submit(queue, &[submit_info], fence)
})?;
self.state.set_pending();
@ -329,7 +329,7 @@ pub mod traits {
queue.with_locked(|queue| unsafe {
self.device()
.dev()
.queue_submit(queue.raw(), &[submit_info], fence.raw())
.queue_submit(queue, &[submit_info], fence.fence())
})?;
tracing::trace!("submitted queue {:?} and fence {:?}", queue, fence);
@ -888,7 +888,7 @@ mod command_pools {
) -> Result<CommandBufferFuture, Error> {
let this = ManuallyDrop::new(self);
if queue.family_index() != this.pool.family {
if queue.1 != this.pool.family {
tracing::error!("attempted to submit commandbuffer to incompatible queue.");
return Err(Error::InvalidQueueSubmission);
}
@ -911,7 +911,7 @@ mod command_pools {
queue.with_locked(|queue| unsafe {
this.device()
.dev()
.queue_submit(queue.raw(), &[submit_info], fence.raw())
.queue_submit(queue, &[submit_info], fence.fence())
})?;
Ok(CommandBufferFuture {
@ -931,7 +931,7 @@ mod command_pools {
}
impl CommandBufferFuture {
pub fn block(&self) -> crate::Result<()> {
pub fn block(&self) -> VkResult<()> {
self.inner.block()
}
}

View file

@ -118,18 +118,6 @@ impl DeviceHandle for GpuAllocation {
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AllocationStrategy {
#[default]
/// Let gpu_allocator manage the memory for this allocation, sub-allocating
/// from larger blocks as needed.
AllocatorManaged,
/// Allocate a dedicated block of memory for this allocation. This is
/// recommended for long-lived resources or resources with specific memory
/// requirements.
Dedicated,
}
#[derive(Debug)]
pub(crate) enum Allocation {
Owned(DeviceObject<GpuAllocation>),
@ -156,6 +144,7 @@ impl Allocation {
}
pub struct DeviceInner {
pub(crate) alloc: vk_mem::Allocator,
pub(crate) alloc2: Mutex<gpu_allocator::vulkan::Allocator>,
pub(crate) raw: ash::Device,
pub(crate) adapter: PhysicalDeviceInfo,
@ -450,6 +439,13 @@ impl PhysicalDeviceInfo {
let inner = DeviceInner {
raw: device.clone(),
alloc: unsafe {
vk_mem::Allocator::new(vk_mem::AllocatorCreateInfo::new(
&instance.inner.raw,
&device,
self.pdev,
))?
},
alloc2: Mutex::new(alloc2),
instance: instance.clone(),
adapter: self,
@ -535,6 +531,9 @@ impl DeviceInner {
pub fn sync_threadpool(&self) -> &sync::SyncThreadpool {
&self.sync_threadpool
}
pub fn alloc(&self) -> &vk_mem::Allocator {
&self.alloc
}
pub fn dev(&self) -> &ash::Device {
&self.raw
}

View file

@ -1,14 +1,13 @@
use std::{collections::BTreeMap, sync::Arc};
use ash::vk;
use gpu_allocator::MemoryLocation;
use ash::{prelude::VkResult, vk};
use indexmap::IndexMap;
use crate::{
EguiState,
buffers::{Buffer, BufferDesc},
commands::traits::CommandBufferExt,
device::{self, AllocationStrategy},
device::{self, DeviceOwned},
images::{Image, ImageDesc, ImageViewDesc},
render_graph::{
Access, Barrier, GraphResourceDesc, GraphResourceId, PassDesc, RecordFn, RenderContext,
@ -24,7 +23,7 @@ pub fn egui_pre_pass(
textures: &mut crate::texture::TextureManager,
egui_state: &mut EguiState,
output: &egui::FullOutput,
) -> crate::Result<()> {
) -> VkResult<()> {
// allocate resource ids for textures in tessellated list (imported from texture manager)
// define accesses for resource ids
@ -51,8 +50,7 @@ pub fn egui_pre_pass(
depth: 1,
},
usage: vk::ImageUsageFlags::SAMPLED | vk::ImageUsageFlags::TRANSFER_DST,
mem_location: MemoryLocation::GpuOnly,
alloc_scheme: AllocationStrategy::Dedicated,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
},
)?;
@ -96,7 +94,10 @@ pub fn egui_pre_pass(
size: staging_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_SRC,
queue_families: device::QueueFlags::empty(),
mem_location: MemoryLocation::CpuToGpu,
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
..Default::default()
},
)?;
@ -114,14 +115,14 @@ pub fn egui_pre_pass(
},
usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST,
queue_families: device::QueueFlags::empty(),
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
},
)?);
let aliased_images = {
tracing::trace!("mmap-ing staging buffer");
let mut staging_map = staging_buffer.map().unwrap();
let mut staging_map = staging_buffer.map()?;
let mut offset = 0;
output
@ -213,7 +214,7 @@ pub fn egui_pre_pass(
let texture = textures.get(&id).and_then(|id| ctx.get_image(*id)).unwrap();
let image: Barrier = image_barrier(
alias.raw(),
alias.handle(),
alias.format(),
Access {
stage: vk::PipelineStageFlags2::NONE,
@ -236,8 +237,8 @@ pub fn egui_pre_pass(
}
ctx.cmd.copy_buffer_to_image(
staging_buffer.raw(),
alias.raw(),
staging_buffer.handle(),
alias.handle(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[vk::BufferImageCopy {
buffer_offset: offset as u64,
@ -254,7 +255,7 @@ pub fn egui_pre_pass(
);
let from_barrier = image_barrier(
alias.raw(),
alias.handle(),
alias.format(),
Access {
stage: vk::PipelineStageFlags2::TRANSFER,
@ -270,7 +271,7 @@ pub fn egui_pre_pass(
);
let to_barrier = image_barrier(
texture.raw(),
texture.handle(),
texture.format(),
Access {
stage: vk::PipelineStageFlags2::NONE,
@ -303,9 +304,9 @@ pub fn egui_pre_pass(
);
}
ctx.cmd.copy_images(
alias.raw(),
alias.handle(),
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
texture.raw(),
texture.handle(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[vk::ImageCopy {
src_subresource: vk::ImageSubresourceLayers::default()
@ -329,7 +330,7 @@ pub fn egui_pre_pass(
);
let image: Barrier = image_barrier(
texture.raw(),
texture.handle(),
texture.format(),
Access {
stage: vk::PipelineStageFlags2::TRANSFER,
@ -396,7 +397,7 @@ pub fn egui_pass(
egui: &egui::Context,
output: egui::FullOutput,
target: GraphResourceId,
) -> crate::Result<Vec<texture::TextureId>> {
) -> VkResult<Vec<texture::TextureId>> {
let draw_data = egui.tessellate(output.shapes, output.pixels_per_point);
#[repr(C)]
@ -460,13 +461,16 @@ pub fn egui_pass(
name: Some("egui-draw-staging".into()),
size: staging_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_SRC,
mem_location: MemoryLocation::CpuToGpu,
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
..Default::default()
},
)?;
{
let map = staging.map_mut().unwrap();
let mut map = staging.map()?;
let (st_vertices, rest) = map.split_at_mut(vertices_size);
let (st_indices, st_drawcalls) = rest.split_at_mut(indices_size);
@ -480,21 +484,21 @@ pub fn egui_pass(
name: Some("egui-draw-vertices".into()),
size: vertices_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
}));
let indices = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
name: Some("egui-draw-indices".into()),
size: indices_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
}));
let draw_calls = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
name: Some("egui-draw-draw_calls".into()),
size: draw_calls_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDIRECT_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
}));
@ -504,14 +508,13 @@ pub fn egui_pass(
name: Some("egui-draw-texture_ids".into()),
size: (textures_indices.len() * size_of::<u32>()) as u64,
usage: vk::BufferUsageFlags::STORAGE_BUFFER,
mem_location: MemoryLocation::CpuToGpu,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
alloc_flags: vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE,
..Default::default()
},
)?;
{
let map = texture_ids
.map_mut()
.expect("texture id buffer should be device visible");
let mut map = texture_ids.map()?;
map.copy_from_slice(bytemuck::cast_slice(&textures_indices));
}
@ -525,20 +528,22 @@ pub fn egui_pass(
vk::DescriptorImageInfo {
sampler: samplers.get_sampler(entry.as_sampler_desc()).unwrap(),
image_view: texture
.create_view(
ImageViewDesc::color_2d()
.with_mip_range(0..1)
.with_layer_range(0..1),
)
.unwrap()
.raw(),
.get_view(ImageViewDesc {
kind: vk::ImageViewType::TYPE_2D,
format: texture.format(),
aspect: vk::ImageAspectFlags::COLOR,
mip_range: (0..1).into(),
layer_range: (0..1).into(),
..Default::default()
})
.unwrap(),
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
}
})
.collect::<Vec<_>>();
let uniform_info = vk::DescriptorBufferInfo {
buffer: texture_ids.raw(),
buffer: texture_ids.buffer(),
offset: 0,
range: texture_ids.len(),
};
@ -604,8 +609,8 @@ pub fn egui_pass(
let target = ctx.get_image(target).unwrap();
cmd.copy_buffers(
staging.raw(),
vertices.raw(),
staging.buffer(),
vertices.buffer(),
&[vk::BufferCopy {
src_offset: 0,
dst_offset: 0,
@ -613,8 +618,8 @@ pub fn egui_pass(
}],
);
cmd.copy_buffers(
staging.raw(),
indices.raw(),
staging.buffer(),
indices.buffer(),
&[vk::BufferCopy {
src_offset: vertices_size as u64,
dst_offset: 0,
@ -622,8 +627,8 @@ pub fn egui_pass(
}],
);
cmd.copy_buffers(
staging.raw(),
draw_calls.raw(),
staging.buffer(),
draw_calls.buffer(),
&[vk::BufferCopy {
src_offset: (vertices_size + indices_size) as u64,
dst_offset: 0,
@ -633,7 +638,7 @@ pub fn egui_pass(
let barriers = [
buffer_barrier(
vertices.raw(),
vertices.handle(),
0,
vertices.len(),
Access::transfer_write(),
@ -641,7 +646,7 @@ pub fn egui_pass(
None,
),
buffer_barrier(
indices.raw(),
indices.handle(),
0,
indices.len(),
Access::transfer_write(),
@ -649,7 +654,7 @@ pub fn egui_pass(
None,
),
buffer_barrier(
draw_calls.raw(),
draw_calls.handle(),
0,
draw_calls.len(),
Access::transfer_write(),
@ -666,7 +671,12 @@ pub fn egui_pass(
let color_attachment = &vk::RenderingAttachmentInfo::default()
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
.image_view(target.create_view(ImageViewDesc::color_2d())?.raw())
.image_view(target.get_view(ImageViewDesc {
kind: vk::ImageViewType::TYPE_2D,
format: target.format(),
aspect: vk::ImageAspectFlags::COLOR,
..Default::default()
})?)
.load_op(vk::AttachmentLoadOp::LOAD)
.store_op(vk::AttachmentStoreOp::STORE);
@ -690,8 +700,8 @@ pub fn egui_pass(
.height(target.height() as f32)]);
cmd.bind_pipeline(&pipeline);
cmd.bind_indices(indices.raw(), 0, vk::IndexType::UINT32);
cmd.bind_vertex_buffers(&[vertices.raw()], &[0]);
cmd.bind_indices(indices.buffer(), 0, vk::IndexType::UINT32);
cmd.bind_vertex_buffers(&[vertices.buffer()], &[0]);
cmd.push_constants(
&pipeline_layout,
vk::ShaderStageFlags::VERTEX,
@ -706,7 +716,7 @@ pub fn egui_pass(
&[descriptor_set],
);
cmd.draw_indexed_indirect(
draw_calls.raw(),
draw_calls.buffer(),
0,
num_draw_calls as u32,
size_of::<vk::DrawIndexedIndirectCommand>() as u32,

View file

@ -1,15 +1,21 @@
use std::{borrow::Cow, sync::Arc};
use std::{
borrow::Cow,
collections::HashMap,
sync::{Arc, Weak},
};
use crate::{
device::{Allocation, AllocationStrategy, DeviceHandle, DeviceObject, QueueFlags},
define_device_owned_handle,
device::{Allocation, DeviceHandle, DeviceObject, DeviceOwned, QueueFlags},
swapchain::Swapchain,
util::weak_vec::WeakVec,
};
use super::Device;
use ash::vk;
use ash::{prelude::*, vk};
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
use parking_lot::Mutex;
use vk_mem::Alloc;
#[derive(Clone)]
pub struct ImageDesc {
@ -27,7 +33,6 @@ pub struct ImageDesc {
pub layout: vk::ImageLayout,
pub mem_location: gpu_allocator::MemoryLocation,
pub alloc_scheme: AllocationStrategy,
}
impl std::hash::Hash for ImageDesc {
@ -82,7 +87,6 @@ impl<'a> std::fmt::Debug for ImageDesc {
.field("queue_families", &self.queue_families)
.field("layout", &self.layout)
.field("mem_location", &self.mem_location)
.field("alloc_scheme", &self.alloc_scheme)
.finish()
}
}
@ -103,7 +107,6 @@ impl Default for ImageDesc {
queue_families: QueueFlags::empty(),
layout: vk::ImageLayout::UNDEFINED,
mem_location: gpu_allocator::MemoryLocation::Unknown,
alloc_scheme: AllocationStrategy::AllocatorManaged,
}
}
}
@ -165,10 +168,7 @@ impl Image {
requirements,
location: desc.mem_location,
linear: desc.tiling == vk::ImageTiling::LINEAR,
allocation_scheme: match desc.alloc_scheme {
AllocationStrategy::AllocatorManaged => AllocationScheme::GpuAllocatorManaged,
AllocationStrategy::Dedicated => AllocationScheme::DedicatedImage(image),
},
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
})?;
Ok(Self {
@ -316,10 +316,6 @@ impl Image {
Ok((image, requirements))
}
pub fn raw(&self) -> vk::Image {
self.image.image()
}
}
impl Eq for Image {}
@ -363,35 +359,35 @@ impl Image {
self.image.allocation_mut()
}
// /// 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))
// }
// }
// }
/// 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: &Arc<Self>, mut desc: ImageViewDesc) -> crate::Result<ImageView> {
pub fn create_view(&self, desc: ImageViewDesc) -> crate::Result<ImageView> {
// validate
if !view_kind_compatible(self.desc.kind, desc.kind) {
tracing::error!(
@ -411,24 +407,7 @@ impl Image {
desc.mip_range,
self.desc.mip_levels
);
return Err(crate::Error::Todo(
"image view mip range exceeds image mip levels",
));
}
if desc.format == vk::Format::UNDEFINED {
desc.format = self.desc.format;
}
if !validate_image_view_format(&self.desc, desc.format) {
tracing::error!(
"image view format {:?} is not compatible with image format {:?}",
desc.format,
self.desc.format
);
return Err(crate::Error::Todo(
"image view format is not compatible with image format",
));
return Err(crate::Error::Unspecified);
}
let create_info = vk::ImageViewCreateInfo::default()
@ -449,22 +428,7 @@ impl Image {
let device = self.image.device();
let view = unsafe { device.raw.create_image_view(&create_info, None)? };
Ok(ImageView {
view: DeviceObject::new(view, device.clone(), desc.name.clone()),
desc,
image: self.clone(),
})
}
}
fn validate_image_view_format(image: &ImageDesc, view_format: vk::Format) -> bool {
let mutable = image.flags.contains(vk::ImageCreateFlags::MUTABLE_FORMAT);
if mutable {
image.format == view_format
|| FormatClass::from(image.format) == FormatClass::from(view_format)
} else {
image.format == view_format
ImageView::construct(self.device().clone(), view, desc.name)
}
}
@ -492,44 +456,7 @@ pub struct ImageViewDesc {
}
impl ImageViewDesc {
pub fn color_2d() -> Self {
Self {
kind: vk::ImageViewType::TYPE_2D,
aspect: vk::ImageAspectFlags::COLOR,
..Default::default()
}
}
pub fn with_format(self, format: vk::Format) -> Self {
Self { format, ..self }
}
pub fn with_mip_range<R: core::ops::RangeBounds<u32>>(self, range: R) -> Self {
Self {
mip_range: range.into(),
..self
}
}
pub fn with_layer_range<R: core::ops::RangeBounds<u32>>(self, range: R) -> Self {
Self {
layer_range: range.into(),
..self
}
}
pub fn with_aspect(self, aspect: vk::ImageAspectFlags) -> Self {
Self { aspect, ..self }
}
pub fn with_name(self, name: impl Into<Cow<'static, str>>) -> Self {
Self {
name: Some(name.into()),
..self
}
}
pub(crate) fn hash_eq_copy(&self) -> Self {
pub fn hash_eq_copy(&self) -> Self {
let &Self {
flags,
kind,
@ -634,15 +561,6 @@ pub struct ImageView {
image: Arc<Image>,
}
impl ImageView {
pub fn raw(&self) -> vk::ImageView {
*self.view
}
pub fn image(&self) -> &Arc<Image> {
&self.image
}
}
impl DeviceHandle for vk::ImageView {
unsafe fn destroy(&mut self, device: &Device) {
unsafe {
@ -671,487 +589,3 @@ pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange = vk::ImageSubre
base_array_layer: 0,
layer_count: vk::REMAINING_ARRAY_LAYERS,
};
// copilot generated from spec:
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FormatClass {
Bits8,
Bits16,
Alpha8,
Bits24,
Bits32,
Bits48,
Bits64,
Bits96,
Bits128,
Bits192,
Bits256,
D16,
D24,
D32,
S8,
D16S8,
D24S8,
D32S8,
Bc1Rgb,
Bc1Rgba,
Bc2,
Bc3,
Bc4,
Bc5,
Bc6h,
Bc7,
Etc2Rgb,
Etc2Rgba,
Etc2EacRgba,
EacR,
EacRg,
Astc4x4,
Astc5x4,
Astc5x5,
Astc6x5,
Astc6x6,
Astc8x5,
Astc8x6,
Astc8x8,
Astc10x5,
Astc10x6,
Astc10x8,
Astc10x10,
Astc12x10,
Astc12x12,
YuvG8B8G8R8_422,
YuvB8G8R8G8_422,
YuvG8B8R8Triplane420,
YuvG8B8R8Biplane420,
YuvG8B8R8Triplane422,
YuvG8B8R8Biplane422,
YuvG8B8R8Triplane444,
YuvG10X6B10X6R10X6Triplane420,
YuvG10X6B10X6R10X6Biplane420,
YuvG10X6B10X6R10X6Triplane422,
YuvG10X6B10X6R10X6Biplane422,
YuvG10X6B10X6R10X6Triplane444,
YuvG12X4B12X4R12X4Triplane420,
YuvG12X4B12X4R12X4Biplane420,
YuvG12X4B12X4R12X4Triplane422,
YuvG12X4B12X4R12X4Biplane422,
YuvG12X4B12X4R12X4Triplane444,
YuvG16B16R16Triplane420,
YuvG16B16R16Biplane420,
YuvG16B16R16Triplane422,
YuvG16B16R16Biplane422,
YuvG16B16R16Triplane444,
YuvG8B8R8Biplane444,
YuvG10X6B10X6R10X6Biplane444,
YuvG12X4B12X4R12X4Biplane444,
YuvG16B16R16Biplane444,
Bits64R10G10B10A10,
Bits64G10B10G10R10_422,
Bits64B10G10R10G10_422,
Bits64R12G12B12A12,
Bits64G12B12G12R12_422,
Bits64B12G12R12G12_422,
Bits64G16B16G16R16_422,
Bits64B16G16R16G16_422,
Bits64R14G14B14A14,
Pvrtc1_2bpp,
Pvrtc1_4bpp,
Pvrtc2_2bpp,
Pvrtc2_4bpp,
Astc3x3x3,
Astc4x3x3,
Astc4x4x3,
Astc4x4x4,
Astc5x4x4,
Astc5x5x4,
Astc5x5x5,
Astc6x5x5,
Astc6x6x5,
Astc6x6x6,
YuvG14X2B14X2R14X2Biplane420,
YuvG14X2B14X2R14X2Biplane422,
}
impl From<vk::Format> for FormatClass {
fn from(format: vk::Format) -> Self {
use vk::Format as F;
match format {
// 8-bit
F::R4G4_UNORM_PACK8
| F::R8_UNORM
| F::R8_SNORM
| F::R8_USCALED
| F::R8_SSCALED
// | F::R8_BOOL_ARM
// | F::R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM
// | F::R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM
| F::R8_UINT
| F::R8_SINT
| F::R8_SRGB => FormatClass::Bits8,
// 16-bit
F::A1B5G5R5_UNORM_PACK16_KHR
| F::R10X6_UNORM_PACK16
| F::R12X4_UNORM_PACK16
| F::A4R4G4B4_UNORM_PACK16
| F::A4B4G4R4_UNORM_PACK16
// | F::R10X6_UINT_PACK16_ARM
// | F::R12X4_UINT_PACK16_ARM
// | F::R14X2_UINT_PACK16_ARM
// | F::R14X2_UNORM_PACK16_ARM
// | F::R16_SFLOAT_FPENCODING_BFLOAT16_ARM
| F::R4G4B4A4_UNORM_PACK16
| F::B4G4R4A4_UNORM_PACK16
| F::R5G6B5_UNORM_PACK16
| F::B5G6R5_UNORM_PACK16
| F::R5G5B5A1_UNORM_PACK16
| F::B5G5R5A1_UNORM_PACK16
| F::A1R5G5B5_UNORM_PACK16
| F::R8G8_UNORM
| F::R8G8_SNORM
| F::R8G8_USCALED
| F::R8G8_SSCALED
| F::R8G8_UINT
| F::R8G8_SINT
| F::R8G8_SRGB
| F::R16_UNORM
| F::R16_SNORM
| F::R16_USCALED
| F::R16_SSCALED
| F::R16_UINT
| F::R16_SINT
| F::R16_SFLOAT => FormatClass::Bits16,
// 8-bit alpha
F::A8_UNORM_KHR => FormatClass::Alpha8,
// 24-bit
F::R8G8B8_UNORM
| F::R8G8B8_SNORM
| F::R8G8B8_USCALED
| F::R8G8B8_SSCALED
| F::R8G8B8_UINT
| F::R8G8B8_SINT
| F::R8G8B8_SRGB
| F::B8G8R8_UNORM
| F::B8G8R8_SNORM
| F::B8G8R8_USCALED
| F::B8G8R8_SSCALED
| F::B8G8R8_UINT
| F::B8G8R8_SINT
| F::B8G8R8_SRGB => FormatClass::Bits24,
// 32-bit
F::R10X6G10X6_UNORM_2PACK16
| F::R12X4G12X4_UNORM_2PACK16
// | F::R16G16_SFIXED5_NV
// | F::R10X6G10X6_UINT_2PACK16_ARM
// | F::R12X4G12X4_UINT_2PACK16_ARM
// | F::R14X2G14X2_UINT_2PACK16_ARM
// | F::R14X2G14X2_UNORM_2PACK16_ARM
| F::R8G8B8A8_UNORM
| F::R8G8B8A8_SNORM
| F::R8G8B8A8_USCALED
| F::R8G8B8A8_SSCALED
| F::R8G8B8A8_UINT
| F::R8G8B8A8_SINT
| F::R8G8B8A8_SRGB
| F::B8G8R8A8_UNORM
| F::B8G8R8A8_SNORM
| F::B8G8R8A8_USCALED
| F::B8G8R8A8_SSCALED
| F::B8G8R8A8_UINT
| F::B8G8R8A8_SINT
| F::B8G8R8A8_SRGB
| F::A8B8G8R8_UNORM_PACK32
| F::A8B8G8R8_SNORM_PACK32
| F::A8B8G8R8_USCALED_PACK32
| F::A8B8G8R8_SSCALED_PACK32
| F::A8B8G8R8_UINT_PACK32
| F::A8B8G8R8_SINT_PACK32
| F::A8B8G8R8_SRGB_PACK32
| F::A2R10G10B10_UNORM_PACK32
| F::A2R10G10B10_SNORM_PACK32
| F::A2R10G10B10_USCALED_PACK32
| F::A2R10G10B10_SSCALED_PACK32
| F::A2R10G10B10_UINT_PACK32
| F::A2R10G10B10_SINT_PACK32
| F::A2B10G10R10_UNORM_PACK32
| F::A2B10G10R10_SNORM_PACK32
| F::A2B10G10R10_USCALED_PACK32
| F::A2B10G10R10_SSCALED_PACK32
| F::A2B10G10R10_UINT_PACK32
| F::A2B10G10R10_SINT_PACK32
| F::R16G16_UNORM
| F::R16G16_SNORM
| F::R16G16_USCALED
| F::R16G16_SSCALED
| F::R16G16_UINT
| F::R16G16_SINT
| F::R16G16_SFLOAT
| F::R32_UINT
| F::R32_SINT
| F::R32_SFLOAT
| F::B10G11R11_UFLOAT_PACK32
| F::E5B9G9R9_UFLOAT_PACK32 => FormatClass::Bits32,
// 48-bit
F::R16G16B16_UNORM
| F::R16G16B16_SNORM
| F::R16G16B16_USCALED
| F::R16G16B16_SSCALED
| F::R16G16B16_UINT
| F::R16G16B16_SINT
| F::R16G16B16_SFLOAT => FormatClass::Bits48,
// 64-bit
F::R16G16B16A16_UNORM
| F::R16G16B16A16_SNORM
| F::R16G16B16A16_USCALED
| F::R16G16B16A16_SSCALED
| F::R16G16B16A16_UINT
| F::R16G16B16A16_SINT
| F::R16G16B16A16_SFLOAT
| F::R32G32_UINT
| F::R32G32_SINT
| F::R32G32_SFLOAT
| F::R64_UINT
| F::R64_SINT
| F::R64_SFLOAT => FormatClass::Bits64,
// 96-bit
F::R32G32B32_UINT | F::R32G32B32_SINT | F::R32G32B32_SFLOAT => FormatClass::Bits96,
// 128-bit
F::R32G32B32A32_UINT
| F::R32G32B32A32_SINT
| F::R32G32B32A32_SFLOAT
| F::R64G64_UINT
| F::R64G64_SINT
| F::R64G64_SFLOAT => FormatClass::Bits128,
// 192-bit
F::R64G64B64_UINT | F::R64G64B64_SINT | F::R64G64B64_SFLOAT => FormatClass::Bits192,
// 256-bit
F::R64G64B64A64_UINT | F::R64G64B64A64_SINT | F::R64G64B64A64_SFLOAT => {
FormatClass::Bits256
}
// Depth / Stencil
F::D16_UNORM => FormatClass::D16,
F::X8_D24_UNORM_PACK32 => FormatClass::D24,
F::D32_SFLOAT => FormatClass::D32,
F::S8_UINT => FormatClass::S8,
F::D16_UNORM_S8_UINT => FormatClass::D16S8,
F::D24_UNORM_S8_UINT => FormatClass::D24S8,
F::D32_SFLOAT_S8_UINT => FormatClass::D32S8,
// BCn
F::BC1_RGB_UNORM_BLOCK | F::BC1_RGB_SRGB_BLOCK => FormatClass::Bc1Rgb,
F::BC1_RGBA_UNORM_BLOCK | F::BC1_RGBA_SRGB_BLOCK => FormatClass::Bc1Rgba,
F::BC2_UNORM_BLOCK | F::BC2_SRGB_BLOCK => FormatClass::Bc2,
F::BC3_UNORM_BLOCK | F::BC3_SRGB_BLOCK => FormatClass::Bc3,
F::BC4_UNORM_BLOCK | F::BC4_SNORM_BLOCK => FormatClass::Bc4,
F::BC5_UNORM_BLOCK | F::BC5_SNORM_BLOCK => FormatClass::Bc5,
F::BC6H_UFLOAT_BLOCK | F::BC6H_SFLOAT_BLOCK => FormatClass::Bc6h,
F::BC7_UNORM_BLOCK | F::BC7_SRGB_BLOCK => FormatClass::Bc7,
// ETC2 / EAC
F::ETC2_R8G8B8_UNORM_BLOCK | F::ETC2_R8G8B8_SRGB_BLOCK => FormatClass::Etc2Rgb,
F::ETC2_R8G8B8A1_UNORM_BLOCK | F::ETC2_R8G8B8A1_SRGB_BLOCK => FormatClass::Etc2Rgba,
F::ETC2_R8G8B8A8_UNORM_BLOCK | F::ETC2_R8G8B8A8_SRGB_BLOCK => FormatClass::Etc2EacRgba,
F::EAC_R11_UNORM_BLOCK | F::EAC_R11_SNORM_BLOCK => FormatClass::EacR,
F::EAC_R11G11_UNORM_BLOCK | F::EAC_R11G11_SNORM_BLOCK => FormatClass::EacRg,
// ASTC 2D
F::ASTC_4X4_SFLOAT_BLOCK | F::ASTC_4X4_UNORM_BLOCK | F::ASTC_4X4_SRGB_BLOCK => {
FormatClass::Astc4x4
}
F::ASTC_5X4_SFLOAT_BLOCK | F::ASTC_5X4_UNORM_BLOCK | F::ASTC_5X4_SRGB_BLOCK => {
FormatClass::Astc5x4
}
F::ASTC_5X5_SFLOAT_BLOCK | F::ASTC_5X5_UNORM_BLOCK | F::ASTC_5X5_SRGB_BLOCK => {
FormatClass::Astc5x5
}
F::ASTC_6X5_SFLOAT_BLOCK | F::ASTC_6X5_UNORM_BLOCK | F::ASTC_6X5_SRGB_BLOCK => {
FormatClass::Astc6x5
}
F::ASTC_6X6_SFLOAT_BLOCK | F::ASTC_6X6_UNORM_BLOCK | F::ASTC_6X6_SRGB_BLOCK => {
FormatClass::Astc6x6
}
F::ASTC_8X5_SFLOAT_BLOCK | F::ASTC_8X5_UNORM_BLOCK | F::ASTC_8X5_SRGB_BLOCK => {
FormatClass::Astc8x5
}
F::ASTC_8X6_SFLOAT_BLOCK | F::ASTC_8X6_UNORM_BLOCK | F::ASTC_8X6_SRGB_BLOCK => {
FormatClass::Astc8x6
}
F::ASTC_8X8_SFLOAT_BLOCK | F::ASTC_8X8_UNORM_BLOCK | F::ASTC_8X8_SRGB_BLOCK => {
FormatClass::Astc8x8
}
F::ASTC_10X5_SFLOAT_BLOCK | F::ASTC_10X5_UNORM_BLOCK | F::ASTC_10X5_SRGB_BLOCK => {
FormatClass::Astc10x5
}
F::ASTC_10X6_SFLOAT_BLOCK | F::ASTC_10X6_UNORM_BLOCK | F::ASTC_10X6_SRGB_BLOCK => {
FormatClass::Astc10x6
}
F::ASTC_10X8_SFLOAT_BLOCK | F::ASTC_10X8_UNORM_BLOCK | F::ASTC_10X8_SRGB_BLOCK => {
FormatClass::Astc10x8
}
F::ASTC_10X10_SFLOAT_BLOCK | F::ASTC_10X10_UNORM_BLOCK | F::ASTC_10X10_SRGB_BLOCK => {
FormatClass::Astc10x10
}
F::ASTC_12X10_SFLOAT_BLOCK | F::ASTC_12X10_UNORM_BLOCK | F::ASTC_12X10_SRGB_BLOCK => {
FormatClass::Astc12x10
}
F::ASTC_12X12_SFLOAT_BLOCK | F::ASTC_12X12_UNORM_BLOCK | F::ASTC_12X12_SRGB_BLOCK => {
FormatClass::Astc12x12
}
// Packed/YCbCr-ish (as listed)
F::G8B8G8R8_422_UNORM => FormatClass::YuvG8B8G8R8_422,
F::B8G8R8G8_422_UNORM => FormatClass::YuvB8G8R8G8_422,
F::G8_B8_R8_3PLANE_420_UNORM => FormatClass::YuvG8B8R8Triplane420,
F::G8_B8R8_2PLANE_420_UNORM => FormatClass::YuvG8B8R8Biplane420,
F::G8_B8_R8_3PLANE_422_UNORM => FormatClass::YuvG8B8R8Triplane422,
F::G8_B8R8_2PLANE_422_UNORM => FormatClass::YuvG8B8R8Biplane422,
F::G8_B8_R8_3PLANE_444_UNORM => FormatClass::YuvG8B8R8Triplane444,
F::G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Triplane420
}
F::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Biplane420
}
F::G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Triplane422
}
F::G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Biplane422
}
F::G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Triplane444
}
F::G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Triplane420
}
F::G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Biplane420
}
F::G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Triplane422
}
F::G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Biplane422
}
F::G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Triplane444
}
F::G16_B16_R16_3PLANE_420_UNORM => FormatClass::YuvG16B16R16Triplane420,
F::G16_B16R16_2PLANE_420_UNORM => FormatClass::YuvG16B16R16Biplane420,
F::G16_B16_R16_3PLANE_422_UNORM => FormatClass::YuvG16B16R16Triplane422,
F::G16_B16R16_2PLANE_422_UNORM => FormatClass::YuvG16B16R16Biplane422,
F::G16_B16_R16_3PLANE_444_UNORM => FormatClass::YuvG16B16R16Triplane444,
// 2-plane 444 (additional section)
F::G8_B8R8_2PLANE_444_UNORM => FormatClass::YuvG8B8R8Biplane444,
F::G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 => {
FormatClass::YuvG10X6B10X6R10X6Biplane444
}
F::G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 => {
FormatClass::YuvG12X4B12X4R12X4Biplane444
}
F::G16_B16R16_2PLANE_444_UNORM => FormatClass::YuvG16B16R16Biplane444,
// 64-bit special grouped headings from the markdown
F::R10X6G10X6B10X6A10X6_UNORM_4PACK16 /* | F::R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM */
=> {
FormatClass::Bits64R10G10B10A10
}
F::G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 => FormatClass::Bits64G10B10G10R10_422,
F::B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 => FormatClass::Bits64B10G10R10G10_422,
F::R12X4G12X4B12X4A12X4_UNORM_4PACK16 /*| F::R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM */
=> {
FormatClass::Bits64R12G12B12A12
}
F::G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 => FormatClass::Bits64G12B12G12R12_422,
F::B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 => FormatClass::Bits64B12G12R12G12_422,
F::G16B16G16R16_422_UNORM => FormatClass::Bits64G16B16G16R16_422,
F::B16G16R16G16_422_UNORM => FormatClass::Bits64B16G16R16G16_422,
// F::R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM
// | F::R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM => FormatClass::Bits64_R14G14B14A14,
// PVRTC
F::PVRTC1_2BPP_UNORM_BLOCK_IMG | F::PVRTC1_2BPP_SRGB_BLOCK_IMG => {
FormatClass::Pvrtc1_2bpp
}
F::PVRTC1_4BPP_UNORM_BLOCK_IMG | F::PVRTC1_4BPP_SRGB_BLOCK_IMG => {
FormatClass::Pvrtc1_4bpp
}
F::PVRTC2_2BPP_UNORM_BLOCK_IMG | F::PVRTC2_2BPP_SRGB_BLOCK_IMG => {
FormatClass::Pvrtc2_2bpp
}
F::PVRTC2_4BPP_UNORM_BLOCK_IMG | F::PVRTC2_4BPP_SRGB_BLOCK_IMG => {
FormatClass::Pvrtc2_4bpp
}
// ASTC 3D (EXT)
// F::ASTC_3X3X3_UNORM_BLOCK_EXT
// | F::ASTC_3X3X3_SRGB_BLOCK_EXT
// | F::ASTC_3X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc3x3x3,
// F::ASTC_4X3X3_UNORM_BLOCK_EXT
// | F::ASTC_4X3X3_SRGB_BLOCK_EXT
// | F::ASTC_4X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x3x3,
// F::ASTC_4X4X3_UNORM_BLOCK_EXT
// | F::ASTC_4X4X3_SRGB_BLOCK_EXT
// | F::ASTC_4X4X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x3,
// F::ASTC_4X4X4_UNORM_BLOCK_EXT
// | F::ASTC_4X4X4_SRGB_BLOCK_EXT
// | F::ASTC_4X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x4,
// F::ASTC_5X4X4_UNORM_BLOCK_EXT
// | F::ASTC_5X4X4_SRGB_BLOCK_EXT
// | F::ASTC_5X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x4x4,
// F::ASTC_5X5X4_UNORM_BLOCK_EXT
// | F::ASTC_5X5X4_SRGB_BLOCK_EXT
// | F::ASTC_5X5X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x4,
// F::ASTC_5X5X5_UNORM_BLOCK_EXT
// | F::ASTC_5X5X5_SRGB_BLOCK_EXT
// | F::ASTC_5X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x5,
// F::ASTC_6X5X5_UNORM_BLOCK_EXT
// | F::ASTC_6X5X5_SRGB_BLOCK_EXT
// | F::ASTC_6X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x5x5,
// F::ASTC_6X6X5_UNORM_BLOCK_EXT
// | F::ASTC_6X6X5_SRGB_BLOCK_EXT
// | F::ASTC_6X6X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x5,
// F::ASTC_6X6X6_UNORM_BLOCK_EXT
// | F::ASTC_6X6X6_SRGB_BLOCK_EXT
// | F::ASTC_6X6X6_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x6,
// // 14-bit 2-plane
// F::G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM => {
// FormatClass::YuvG14X2_B14X2R14X2_2Plane_420
// }
// F::G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM => {
// FormatClass::YuvG14X2_B14X2R14X2_2Plane_422
// }
_ => todo!(),
}
}
}

View file

@ -1,4 +1,5 @@
use std::{
cell::OnceCell,
cmp::Ordering,
ffi::{CStr, CString},
ops::Deref,

View file

@ -118,8 +118,6 @@ pub enum Error {
},
#[error("Unspecified Error")]
Unspecified,
#[error("BEEP BOOP create an error variant for {0} BEEP BOOP")]
Todo(&'static str),
}
pub type Result<T> = core::result::Result<T, Error>;
@ -1023,13 +1021,10 @@ impl Renderer2 {
surface: &swapchain::Surface,
cb: F,
) -> Result<T> {
let Some(frame) = surface.acquire_image() else {
return Err(Error::SuboptimalSwapchain);
};
let (frame, _suboptimal) = frame.await?;
let frame = surface.acquire_image().await?;
let mut rg = render_graph::RenderGraph::new();
let _framebuffer = rg.import_framebuffer(frame.image().clone());
let _framebuffer = rg.import_framebuffer(frame.image.clone());
let out = cb(self, &mut rg);

View file

@ -47,15 +47,6 @@ pub struct QueueInner {
pub(crate) lock: Mutex<()>,
}
impl QueueInner {
pub fn raw(&self) -> vk::Queue {
self.raw
}
pub fn family_index(&self) -> u32 {
self.family.index
}
}
#[derive(Debug, Clone, Copy)]
pub struct QueueFamily {
pub index: u32,

View file

@ -10,7 +10,7 @@ use crate::{
buffers::{Buffer, BufferDesc},
commands::{self, traits::CommandBufferExt},
def_monotonic_id,
device::{self},
device::{self, DeviceOwned},
images::{self, Image, ImageDesc},
util::{self, Rgba, WithLifetime},
};
@ -62,11 +62,13 @@ impl GraphResource {
discr.hash(&mut state);
match self {
GraphResource::Framebuffer(swapchain_frame) => (swapchain_frame.raw()).hash(&mut state),
GraphResource::ImportedImage(image) => image.raw().hash(&mut state),
GraphResource::ImportedBuffer(buffer) => buffer.raw().hash(&mut state),
GraphResource::Image(image) => image.raw().hash(&mut state),
GraphResource::Buffer(buffer) => buffer.raw().hash(&mut state),
GraphResource::Framebuffer(swapchain_frame) => {
(swapchain_frame.handle()).hash(&mut state)
}
GraphResource::ImportedImage(image) => image.handle().hash(&mut state),
GraphResource::ImportedBuffer(buffer) => buffer.handle().hash(&mut state),
GraphResource::Image(image) => image.handle().hash(&mut state),
GraphResource::Buffer(buffer) => buffer.handle().hash(&mut state),
GraphResource::ImageDesc(image_desc) => image_desc.hash(&mut state),
GraphResource::BufferDesc(buffer_desc) => buffer_desc.hash(&mut state),
GraphResource::Default => {}
@ -484,7 +486,7 @@ impl RenderGraph {
_ => {}
}
}
crate::Result::Ok(())
ash::prelude::VkResult::Ok(())
})?;
let pool =
@ -559,19 +561,19 @@ impl RenderGraph {
) {
let barrier: Barrier = match res {
GraphResource::Framebuffer(arc) => {
image_barrier(arc.raw(), arc.format(), from, to, None).into()
image_barrier(arc.handle(), arc.format(), from, to, None).into()
}
GraphResource::ImportedImage(arc) => {
image_barrier(arc.raw(), arc.format(), from, to, None).into()
image_barrier(arc.handle(), arc.format(), from, to, None).into()
}
GraphResource::ImportedBuffer(arc) => {
buffer_barrier(arc.raw(), 0, arc.len(), from, to, None).into()
buffer_barrier(arc.handle(), 0, arc.len(), from, to, None).into()
}
GraphResource::Image(image) => {
image_barrier(image.raw(), image.format(), from, to, None).into()
image_barrier(image.handle(), image.format(), from, to, None).into()
}
GraphResource::Buffer(buffer) => {
buffer_barrier(buffer.raw(), 0, buffer.len(), from, to, None).into()
buffer_barrier(buffer.handle(), 0, buffer.len(), from, to, None).into()
}
_ => {
unreachable!()
@ -1295,7 +1297,7 @@ pub fn clear_pass(rg: &mut RenderGraph, color: Rgba, target: GraphResourceId) {
let cmd = &ctx.cmd;
cmd.clear_color_image(
target.raw(),
target.handle(),
target.format(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
color,

View file

@ -2,7 +2,6 @@ use std::sync::Arc;
use ash::vk;
use glam::{f32::Mat4, vec3};
use gpu_allocator::MemoryLocation;
pub use crate::egui_pass::{egui_pass, egui_pre_pass};
@ -10,7 +9,7 @@ use crate::{
Result,
buffers::{Buffer, BufferDesc},
commands::{self, traits::CommandBufferExt},
device::Device,
device::{Device, DeviceOwned},
images::ImageViewDesc,
pipeline,
render_graph::{
@ -51,15 +50,16 @@ impl Wireframe {
name: Some("wireframe-staging".into()),
size: staging_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_SRC,
mem_location: MemoryLocation::CpuToGpu,
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
..Default::default()
},
)?;
{
let map = staging
.map_mut()
.expect("staging buffer should be host visible");
let mut map = staging.map()?;
map[..positions_size].copy_from_slice(bytemuck::cast_slice(&positions));
map[indices_offset..][..indices_size].copy_from_slice(bytemuck::cast_slice(&indices));
@ -72,7 +72,7 @@ impl Wireframe {
name: Some("wireframe-positions".into()),
size: positions_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
},
)?;
@ -82,7 +82,7 @@ impl Wireframe {
name: Some("wireframe-indices".into()),
size: indices_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
},
)?;
@ -92,7 +92,7 @@ impl Wireframe {
name: Some("wireframe-colors".into()),
size: colors_size as u64,
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
mem_location: MemoryLocation::GpuOnly,
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
..Default::default()
},
)?;
@ -102,8 +102,8 @@ impl Wireframe {
let cmd = pool.alloc()?;
cmd.copy_buffers(
staging.raw(),
positions.raw(),
staging.handle(),
positions.handle(),
&[vk::BufferCopy {
src_offset: 0,
dst_offset: 0,
@ -111,8 +111,8 @@ impl Wireframe {
}],
);
cmd.copy_buffers(
staging.raw(),
indices.raw(),
staging.handle(),
indices.handle(),
&[vk::BufferCopy {
src_offset: indices_offset as u64,
dst_offset: 0,
@ -120,8 +120,8 @@ impl Wireframe {
}],
);
cmd.copy_buffers(
staging.raw(),
colors.raw(),
staging.handle(),
colors.handle(),
&[vk::BufferCopy {
src_offset: colors_offset as u64,
dst_offset: 0,
@ -131,7 +131,7 @@ impl Wireframe {
let barriers = [
buffer_barrier(
positions.raw(),
positions.handle(),
0,
positions.len(),
Access::transfer_write(),
@ -139,7 +139,7 @@ impl Wireframe {
None,
),
buffer_barrier(
indices.raw(),
indices.handle(),
0,
indices.len(),
Access::transfer_write(),
@ -147,7 +147,7 @@ impl Wireframe {
None,
),
buffer_barrier(
colors.raw(),
colors.handle(),
0,
colors.len(),
Access::transfer_write(),
@ -334,7 +334,12 @@ impl Wireframe {
let color_attachment = &vk::RenderingAttachmentInfo::default()
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
.image_view(target.create_view(ImageViewDesc::color_2d())?.raw())
.image_view(target.get_view(ImageViewDesc {
kind: vk::ImageViewType::TYPE_2D,
format: target.format(),
aspect: vk::ImageAspectFlags::COLOR,
..Default::default()
})?)
.load_op(vk::AttachmentLoadOp::LOAD)
.store_op(vk::AttachmentStoreOp::STORE);
@ -358,8 +363,8 @@ impl Wireframe {
.height(target.height() as f32)]);
cmd.bind_pipeline(&pipeline);
cmd.bind_indices(indices.raw(), 0, vk::IndexType::UINT32);
cmd.bind_vertex_buffers(&[positions.raw(), colors.raw()], &[0, 0]);
cmd.bind_indices(indices.buffer(), 0, vk::IndexType::UINT32);
cmd.bind_vertex_buffers(&[positions.handle(), colors.handle()], &[0, 0]);
cmd.push_constants(
&layout,
vk::ShaderStageFlags::VERTEX,

View file

@ -1,6 +1,6 @@
use std::{
collections::HashMap,
ops::Deref,
marker::PhantomData,
sync::{
Arc,
atomic::{AtomicU32, AtomicU64, Ordering},
@ -12,14 +12,16 @@ use ash::{
prelude::VkResult,
vk::{self, Handle},
};
use parking_lot::{Mutex, RwLock};
use parking_lot::{Mutex, RawMutex, RwLock};
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use crate::{
Instance, PhysicalDeviceInfo, Result, SurfaceCapabilities,
device::{Device, DeviceObject},
images::{self, ImageViewDesc},
sync::Fence,
Instance, PhysicalDeviceInfo, Result, SurfaceCapabilities, define_device_owned_handle,
device::{Device, DeviceObject, DeviceOwned},
images,
instance::InstanceInner,
sync::{self, Fence},
util::RawMutexGuard,
};
use derive_more::Debug;
@ -272,18 +274,6 @@ impl Surface {
composite_alpha_mode,
})
}
pub fn acquire_image(
&self,
) -> Option<impl std::future::Future<Output = crate::Result<(SwapchainImage, bool)>>> {
// ensure lock does not block for the entire duration of the async image acquisition.
let swapchain = self.swapchain.read().as_ref().cloned();
if let Some(swapchain) = swapchain {
Some(swapchain.acquire_image())
} else {
None
}
}
}
#[derive(Debug)]
@ -312,7 +302,7 @@ pub struct Swapchain {
// Some of the swapchain operations require external synchronisation; this mutex allows `Swapchain` to be `Sync`.
#[debug(skip)]
pub(crate) guard: parking_lot::Mutex<()>,
guard: parking_lot::RawMutex,
// for khr_present_id/khr_present_wait
#[allow(unused)]
@ -375,7 +365,7 @@ impl Swapchain {
.expect("swapchain extension not loaded");
let (swapchain, images) = {
let _lock = old_swapchain.as_ref().map(|old| old.guard.lock());
let _lock = old_swapchain.as_ref().map(|old| old.lock());
let old_swapchain = old_swapchain
.map(|swp| *swp.swapchain)
.unwrap_or(vk::SwapchainKHR::null());
@ -477,7 +467,7 @@ impl Swapchain {
),
images,
config,
guard: Mutex::new(()),
guard: <RawMutex as parking_lot::lock_api::RawMutex>::INIT,
min_image_count: surface_caps.capabilities.min_image_count,
acquire_semaphores,
release_semaphores,
@ -495,15 +485,11 @@ impl Swapchain {
self.images.len() as u32
}
pub fn raw(&self) -> vk::SwapchainKHR {
*self.swapchain
}
/// returns a future yielding the frame, and true if the swapchain is
/// suboptimal and should be recreated.
fn acquire_image(
self: Arc<Self>,
) -> impl std::future::Future<Output = crate::Result<(SwapchainImage, bool)>> {
) -> impl std::future::Future<Output = crate::Result<(SwapchainFrame, bool)>> {
let frame = self
.current_frame
.try_update(Ordering::Release, Ordering::Relaxed, |i| {
@ -521,34 +507,28 @@ impl Swapchain {
// spawn on threadpool because it might block.
let (idx, suboptimal) = smol::unblock({
let this = self.clone();
let fence = fence.raw();
move || unsafe {
this.with_locked(|swapchain| {
this.functor
.acquire_next_image(swapchain.raw(), u64::MAX, acquire, fence)
.acquire_next_image(swapchain, u64::MAX, acquire, fence.raw())
})
}
})
.await?;
let idx = idx as usize;
let image = self.images[idx].clone();
let image = Arc::new(images::Image::from_swapchain_image(image, &self));
let view = image.create_view(ImageViewDesc {
name: Some(format!("swapchain-{:x}-image-view-{idx}", self.raw().as_raw()).into()),
kind: vk::ImageViewType::TYPE_2D,
format: self.config.format,
aspect: vk::ImageAspectFlags::COLOR,
..Default::default()
})?;
// wait for image to become available.
fence.into_future().await;
let idx = idx as usize;
let image = self.images[idx].clone();
let view = self.image_views[idx];
Ok((
SwapchainImage {
SwapchainFrame {
index: idx as u32,
swapchain: self,
swapchain: self.clone(),
format: self.config.format,
image,
view,
acquire,
release,
@ -558,20 +538,12 @@ impl Swapchain {
}
}
/// # Safety
/// The caller must ensure that the provided index corresponds to an image
/// that is currently acquired and not yet presented.
unsafe fn present(&self, index: u32, wait: Option<vk::Semaphore>) -> Result<()> {
let _lock = self.guard.lock();
fn present(&self, frame: SwapchainFrame, wait: Option<vk::Semaphore>) -> Result<()> {
let swpchain = self.lock();
let queue = self.device().present_queue().lock();
let wait_semaphores = wait.as_slice();
let present_info = vk::PresentInfoKHR::default()
.image_indices(core::slice::from_ref(&index))
.swapchains(core::slice::from_ref(&*self.swapchain))
.wait_semaphores(wait_semaphores);
let queue = self.swapchain.device().queues.graphics();
queue.with_locked(|queue| -> crate::Result<()> {
// TODO: make this optional for devices with no support for present_wait/present_id
// let present_id = self
// .present_id
@ -579,15 +551,18 @@ impl Swapchain {
// let mut present_id =
// vk::PresentIdKHR::default().present_ids(core::slice::from_ref(&present_id));
let present_info = vk::PresentInfoKHR::default()
.image_indices(core::slice::from_ref(&frame.index))
.swapchains(core::slice::from_ref(&swpchain))
.wait_semaphores(wait_semaphores);
//.push_next(&mut present_id)
// call winits pre_present_notify here
unsafe {
self.functor.queue_present(queue.raw(), &present_info)?;
self.functor.queue_present(*queue, &present_info)?;
}
Ok(())
})
}
#[allow(clippy::too_many_arguments)]
@ -640,41 +615,6 @@ impl Swapchain {
}
static SWAPCHAIN_COUNT: AtomicU64 = AtomicU64::new(0);
#[derive(Debug)]
#[must_use = "This struct represents an acquired image from the Swapchain and
must be presented in order to free resources on the device."]
pub struct SwapchainImage {
view: images::ImageView,
// The swapchain must be kept alive while the image is in use, because the
// image is owned by the swapchain and will be freed when the swapchain is
// dropped. Additionally, we need access to the swapchain in order to
// present the image.
swapchain: Arc<Swapchain>,
index: u32,
pub acquire: vk::Semaphore,
pub release: vk::Semaphore,
}
impl Deref for SwapchainImage {
type Target = images::ImageView;
fn deref(&self) -> &Self::Target {
&self.view
}
}
impl SwapchainImage {
pub fn index(&self) -> u32 {
self.index
}
pub fn present(self, wait: Option<vk::Semaphore>) -> crate::Result<()> {
// SAFETY: we know the index is valid because we've aquired the image,
// and we know it isn't presented yet because we still own the image.
unsafe { self.swapchain.present(self.index, wait) }
}
}
#[derive(Debug)]
#[must_use = "This struct represents an acquired image from the swapchain and
must be presented in order to free resources on the device."]
@ -697,8 +637,7 @@ impl PartialEq for SwapchainFrame {
impl SwapchainFrame {
pub fn present(self, wait: Option<vk::Semaphore>) -> crate::Result<()> {
// SAFETY: we know the index is valid because we've aquired the image, and we know it isn't presented yet because we still own the image.
unsafe { self.swapchain.present(self.index, wait) }
self.swapchain.clone().present(self, wait)
}
}
@ -739,9 +678,19 @@ pub struct SwapchainConfiguration {
}
impl Swapchain {
pub fn with_locked<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T {
let _lock = self.guard.lock();
f(self)
pub fn lock(&self) -> RawMutexGuard<'_, vk::SwapchainKHR> {
use parking_lot::lock_api::RawMutex;
self.guard.lock();
RawMutexGuard {
mutex: &self.guard,
value: &*self.swapchain,
_pd: PhantomData,
}
}
pub fn with_locked<T, F: FnOnce(vk::SwapchainKHR) -> T>(&self, f: F) -> T {
let lock = self.lock();
f(*lock)
}
}

View file

@ -3,15 +3,16 @@ use std::borrow::Cow;
use std::{
future::Future,
marker::PhantomData,
mem::ManuallyDrop,
sync::{Arc, atomic::AtomicU32},
time::Duration,
};
use crate::device::{DeviceObject, Pool, PoolObject, Pooled};
use crate::device::{DeviceObject, DeviceOwned, Pool, PoolObject, Pooled};
use crate::{Result, device::DeviceInner};
use super::Device;
use ash::{prelude::VkResult, vk};
use ash::{prelude::*, vk};
use crossbeam::channel::{Receiver, Sender};
type Message = (SyncPrimitive, std::task::Waker);
@ -211,7 +212,7 @@ impl Fence {
}
}
pub fn wait_on(&self, timeout: Option<u64>) -> VkResult<()> {
pub fn wait_on(&self, timeout: Option<u64>) -> Result<()> {
unsafe {
self.device().raw.wait_for_fences(
core::slice::from_ref(&self.raw()),