yeah........
This commit is contained in:
parent
d91ba8c1b7
commit
b0f6c7a1b3
|
|
@ -1,14 +1,11 @@
|
||||||
use std::{
|
use std::borrow::Cow;
|
||||||
borrow::Cow,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use ash::{prelude::VkResult, vk};
|
use ash::vk;
|
||||||
|
use gpu_allocator::vulkan::AllocationScheme;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Device,
|
Device,
|
||||||
device::{Allocation, DeviceObject, QueueFlags},
|
device::{Allocation, AllocationStrategy, DeviceObject, QueueFlags},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -18,7 +15,9 @@ pub struct BufferDesc {
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub usage: vk::BufferUsageFlags,
|
pub usage: vk::BufferUsageFlags,
|
||||||
pub queue_families: QueueFlags,
|
pub queue_families: QueueFlags,
|
||||||
|
|
||||||
pub mem_location: gpu_allocator::MemoryLocation,
|
pub mem_location: gpu_allocator::MemoryLocation,
|
||||||
|
pub alloc_scheme: AllocationStrategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for BufferDesc {
|
impl std::hash::Hash for BufferDesc {
|
||||||
|
|
@ -40,6 +39,7 @@ impl std::fmt::Debug for BufferDesc {
|
||||||
.field("usage", &self.usage)
|
.field("usage", &self.usage)
|
||||||
.field("queue_families", &self.queue_families)
|
.field("queue_families", &self.queue_families)
|
||||||
.field("mem_location", &self.mem_location)
|
.field("mem_location", &self.mem_location)
|
||||||
|
.field("alloc_scheme", &self.alloc_scheme)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +66,7 @@ impl Default for BufferDesc {
|
||||||
usage: Default::default(),
|
usage: Default::default(),
|
||||||
queue_families: QueueFlags::empty(),
|
queue_families: QueueFlags::empty(),
|
||||||
mem_location: gpu_allocator::MemoryLocation::Unknown,
|
mem_location: gpu_allocator::MemoryLocation::Unknown,
|
||||||
|
alloc_scheme: AllocationStrategy::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +98,12 @@ impl Buffer {
|
||||||
requirements,
|
requirements,
|
||||||
location: desc.mem_location,
|
location: desc.mem_location,
|
||||||
linear: true,
|
linear: true,
|
||||||
allocation_scheme: gpu_allocator::vulkan::AllocationScheme::GpuAllocatorManaged,
|
allocation_scheme: match desc.alloc_scheme {
|
||||||
|
AllocationStrategy::AllocatorManaged => {
|
||||||
|
AllocationScheme::GpuAllocatorManaged
|
||||||
|
}
|
||||||
|
AllocationStrategy::Dedicated => AllocationScheme::DedicatedBuffer(buffer),
|
||||||
|
},
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
@ -146,7 +152,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer(&self) -> vk::Buffer {
|
pub fn raw(&self) -> vk::Buffer {
|
||||||
*self.buffer
|
*self.buffer
|
||||||
}
|
}
|
||||||
pub fn len(&self) -> u64 {
|
pub fn len(&self) -> u64 {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ impl Drop for SingleUseCommandPool {
|
||||||
impl SingleUseCommandPool {
|
impl SingleUseCommandPool {
|
||||||
pub fn new(device: Device, queue: Queue) -> VkResult<Arc<Self>> {
|
pub fn new(device: Device, queue: Queue) -> VkResult<Arc<Self>> {
|
||||||
let pool_info = vk::CommandPoolCreateInfo::default()
|
let pool_info = vk::CommandPoolCreateInfo::default()
|
||||||
.queue_family_index(queue.family())
|
.queue_family_index(queue.family_index())
|
||||||
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
||||||
|
|
||||||
let pool = unsafe { device.dev().create_command_pool(&pool_info, None)? };
|
let pool = unsafe { device.dev().create_command_pool(&pool_info, None)? };
|
||||||
|
|
@ -110,7 +110,7 @@ impl<T: HasQueue> CommandList<T> {
|
||||||
self.0[0]
|
self.0[0]
|
||||||
.device()
|
.device()
|
||||||
.dev()
|
.dev()
|
||||||
.queue_submit(queue, &[info], fence.fence())
|
.queue_submit(queue.raw(), &[info], fence.raw())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(FenceFuture::<'a>::new(fence))
|
Ok(FenceFuture::<'a>::new(fence))
|
||||||
|
|
@ -257,7 +257,7 @@ impl SingleUseCommand {
|
||||||
self.pool.queue().with_locked(|queue| unsafe {
|
self.pool.queue().with_locked(|queue| unsafe {
|
||||||
self.device()
|
self.device()
|
||||||
.dev()
|
.dev()
|
||||||
.queue_submit(queue, &[submit_info], fence)
|
.queue_submit(queue.raw(), &[submit_info], fence)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.state.set_pending();
|
self.state.set_pending();
|
||||||
|
|
@ -329,7 +329,7 @@ pub mod traits {
|
||||||
queue.with_locked(|queue| unsafe {
|
queue.with_locked(|queue| unsafe {
|
||||||
self.device()
|
self.device()
|
||||||
.dev()
|
.dev()
|
||||||
.queue_submit(queue, &[submit_info], fence.fence())
|
.queue_submit(queue.raw(), &[submit_info], fence.raw())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
tracing::trace!("submitted queue {:?} and fence {:?}", queue, fence);
|
tracing::trace!("submitted queue {:?} and fence {:?}", queue, fence);
|
||||||
|
|
@ -888,7 +888,7 @@ mod command_pools {
|
||||||
) -> Result<CommandBufferFuture, Error> {
|
) -> Result<CommandBufferFuture, Error> {
|
||||||
let this = ManuallyDrop::new(self);
|
let this = ManuallyDrop::new(self);
|
||||||
|
|
||||||
if queue.1 != this.pool.family {
|
if queue.family_index() != this.pool.family {
|
||||||
tracing::error!("attempted to submit commandbuffer to incompatible queue.");
|
tracing::error!("attempted to submit commandbuffer to incompatible queue.");
|
||||||
return Err(Error::InvalidQueueSubmission);
|
return Err(Error::InvalidQueueSubmission);
|
||||||
}
|
}
|
||||||
|
|
@ -911,7 +911,7 @@ mod command_pools {
|
||||||
queue.with_locked(|queue| unsafe {
|
queue.with_locked(|queue| unsafe {
|
||||||
this.device()
|
this.device()
|
||||||
.dev()
|
.dev()
|
||||||
.queue_submit(queue, &[submit_info], fence.fence())
|
.queue_submit(queue.raw(), &[submit_info], fence.raw())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(CommandBufferFuture {
|
Ok(CommandBufferFuture {
|
||||||
|
|
@ -931,7 +931,7 @@ mod command_pools {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandBufferFuture {
|
impl CommandBufferFuture {
|
||||||
pub fn block(&self) -> VkResult<()> {
|
pub fn block(&self) -> crate::Result<()> {
|
||||||
self.inner.block()
|
self.inner.block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,18 @@ 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)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Allocation {
|
pub(crate) enum Allocation {
|
||||||
Owned(DeviceObject<GpuAllocation>),
|
Owned(DeviceObject<GpuAllocation>),
|
||||||
|
|
@ -144,7 +156,6 @@ impl Allocation {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DeviceInner {
|
pub struct DeviceInner {
|
||||||
pub(crate) alloc: vk_mem::Allocator,
|
|
||||||
pub(crate) alloc2: Mutex<gpu_allocator::vulkan::Allocator>,
|
pub(crate) alloc2: Mutex<gpu_allocator::vulkan::Allocator>,
|
||||||
pub(crate) raw: ash::Device,
|
pub(crate) raw: ash::Device,
|
||||||
pub(crate) adapter: PhysicalDeviceInfo,
|
pub(crate) adapter: PhysicalDeviceInfo,
|
||||||
|
|
@ -439,13 +450,6 @@ impl PhysicalDeviceInfo {
|
||||||
|
|
||||||
let inner = DeviceInner {
|
let inner = DeviceInner {
|
||||||
raw: device.clone(),
|
raw: device.clone(),
|
||||||
alloc: unsafe {
|
|
||||||
vk_mem::Allocator::new(vk_mem::AllocatorCreateInfo::new(
|
|
||||||
&instance.inner.raw,
|
|
||||||
&device,
|
|
||||||
self.pdev,
|
|
||||||
))?
|
|
||||||
},
|
|
||||||
alloc2: Mutex::new(alloc2),
|
alloc2: Mutex::new(alloc2),
|
||||||
instance: instance.clone(),
|
instance: instance.clone(),
|
||||||
adapter: self,
|
adapter: self,
|
||||||
|
|
@ -531,9 +535,6 @@ impl DeviceInner {
|
||||||
pub fn sync_threadpool(&self) -> &sync::SyncThreadpool {
|
pub fn sync_threadpool(&self) -> &sync::SyncThreadpool {
|
||||||
&self.sync_threadpool
|
&self.sync_threadpool
|
||||||
}
|
}
|
||||||
pub fn alloc(&self) -> &vk_mem::Allocator {
|
|
||||||
&self.alloc
|
|
||||||
}
|
|
||||||
pub fn dev(&self) -> &ash::Device {
|
pub fn dev(&self) -> &ash::Device {
|
||||||
&self.raw
|
&self.raw
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
use std::{collections::BTreeMap, sync::Arc};
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use ash::{prelude::VkResult, vk};
|
use ash::vk;
|
||||||
|
use gpu_allocator::MemoryLocation;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
EguiState,
|
EguiState,
|
||||||
buffers::{Buffer, BufferDesc},
|
buffers::{Buffer, BufferDesc},
|
||||||
commands::traits::CommandBufferExt,
|
commands::traits::CommandBufferExt,
|
||||||
device::{self, DeviceOwned},
|
device::{self, AllocationStrategy},
|
||||||
images::{Image, ImageDesc, ImageViewDesc},
|
images::{Image, ImageDesc, ImageViewDesc},
|
||||||
render_graph::{
|
render_graph::{
|
||||||
Access, Barrier, GraphResourceDesc, GraphResourceId, PassDesc, RecordFn, RenderContext,
|
Access, Barrier, GraphResourceDesc, GraphResourceId, PassDesc, RecordFn, RenderContext,
|
||||||
|
|
@ -23,7 +24,7 @@ pub fn egui_pre_pass(
|
||||||
textures: &mut crate::texture::TextureManager,
|
textures: &mut crate::texture::TextureManager,
|
||||||
egui_state: &mut EguiState,
|
egui_state: &mut EguiState,
|
||||||
output: &egui::FullOutput,
|
output: &egui::FullOutput,
|
||||||
) -> VkResult<()> {
|
) -> crate::Result<()> {
|
||||||
// allocate resource ids for textures in tessellated list (imported from texture manager)
|
// allocate resource ids for textures in tessellated list (imported from texture manager)
|
||||||
// define accesses for resource ids
|
// define accesses for resource ids
|
||||||
|
|
||||||
|
|
@ -50,7 +51,8 @@ pub fn egui_pre_pass(
|
||||||
depth: 1,
|
depth: 1,
|
||||||
},
|
},
|
||||||
usage: vk::ImageUsageFlags::SAMPLED | vk::ImageUsageFlags::TRANSFER_DST,
|
usage: vk::ImageUsageFlags::SAMPLED | vk::ImageUsageFlags::TRANSFER_DST,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
|
alloc_scheme: AllocationStrategy::Dedicated,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -94,10 +96,7 @@ pub fn egui_pre_pass(
|
||||||
size: staging_size as u64,
|
size: staging_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
||||||
queue_families: device::QueueFlags::empty(),
|
queue_families: device::QueueFlags::empty(),
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
|
mem_location: MemoryLocation::CpuToGpu,
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
|
|
||||||
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
|
|
||||||
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -115,14 +114,14 @@ pub fn egui_pre_pass(
|
||||||
},
|
},
|
||||||
usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST,
|
usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST,
|
||||||
queue_families: device::QueueFlags::empty(),
|
queue_families: device::QueueFlags::empty(),
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
let aliased_images = {
|
let aliased_images = {
|
||||||
tracing::trace!("mmap-ing staging buffer");
|
tracing::trace!("mmap-ing staging buffer");
|
||||||
let mut staging_map = staging_buffer.map()?;
|
let mut staging_map = staging_buffer.map().unwrap();
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
||||||
output
|
output
|
||||||
|
|
@ -214,7 +213,7 @@ pub fn egui_pre_pass(
|
||||||
let texture = textures.get(&id).and_then(|id| ctx.get_image(*id)).unwrap();
|
let texture = textures.get(&id).and_then(|id| ctx.get_image(*id)).unwrap();
|
||||||
|
|
||||||
let image: Barrier = image_barrier(
|
let image: Barrier = image_barrier(
|
||||||
alias.handle(),
|
alias.raw(),
|
||||||
alias.format(),
|
alias.format(),
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::NONE,
|
stage: vk::PipelineStageFlags2::NONE,
|
||||||
|
|
@ -237,8 +236,8 @@ pub fn egui_pre_pass(
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.cmd.copy_buffer_to_image(
|
ctx.cmd.copy_buffer_to_image(
|
||||||
staging_buffer.handle(),
|
staging_buffer.raw(),
|
||||||
alias.handle(),
|
alias.raw(),
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
&[vk::BufferImageCopy {
|
&[vk::BufferImageCopy {
|
||||||
buffer_offset: offset as u64,
|
buffer_offset: offset as u64,
|
||||||
|
|
@ -255,7 +254,7 @@ pub fn egui_pre_pass(
|
||||||
);
|
);
|
||||||
|
|
||||||
let from_barrier = image_barrier(
|
let from_barrier = image_barrier(
|
||||||
alias.handle(),
|
alias.raw(),
|
||||||
alias.format(),
|
alias.format(),
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
|
|
@ -271,7 +270,7 @@ pub fn egui_pre_pass(
|
||||||
);
|
);
|
||||||
|
|
||||||
let to_barrier = image_barrier(
|
let to_barrier = image_barrier(
|
||||||
texture.handle(),
|
texture.raw(),
|
||||||
texture.format(),
|
texture.format(),
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::NONE,
|
stage: vk::PipelineStageFlags2::NONE,
|
||||||
|
|
@ -304,9 +303,9 @@ pub fn egui_pre_pass(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ctx.cmd.copy_images(
|
ctx.cmd.copy_images(
|
||||||
alias.handle(),
|
alias.raw(),
|
||||||
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
texture.handle(),
|
texture.raw(),
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
&[vk::ImageCopy {
|
&[vk::ImageCopy {
|
||||||
src_subresource: vk::ImageSubresourceLayers::default()
|
src_subresource: vk::ImageSubresourceLayers::default()
|
||||||
|
|
@ -330,7 +329,7 @@ pub fn egui_pre_pass(
|
||||||
);
|
);
|
||||||
|
|
||||||
let image: Barrier = image_barrier(
|
let image: Barrier = image_barrier(
|
||||||
texture.handle(),
|
texture.raw(),
|
||||||
texture.format(),
|
texture.format(),
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
|
|
@ -397,7 +396,7 @@ pub fn egui_pass(
|
||||||
egui: &egui::Context,
|
egui: &egui::Context,
|
||||||
output: egui::FullOutput,
|
output: egui::FullOutput,
|
||||||
target: GraphResourceId,
|
target: GraphResourceId,
|
||||||
) -> VkResult<Vec<texture::TextureId>> {
|
) -> crate::Result<Vec<texture::TextureId>> {
|
||||||
let draw_data = egui.tessellate(output.shapes, output.pixels_per_point);
|
let draw_data = egui.tessellate(output.shapes, output.pixels_per_point);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -461,16 +460,13 @@ pub fn egui_pass(
|
||||||
name: Some("egui-draw-staging".into()),
|
name: Some("egui-draw-staging".into()),
|
||||||
size: staging_size as u64,
|
size: staging_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
|
mem_location: MemoryLocation::CpuToGpu,
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
|
|
||||||
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
|
|
||||||
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut map = staging.map()?;
|
let map = staging.map_mut().unwrap();
|
||||||
|
|
||||||
let (st_vertices, rest) = map.split_at_mut(vertices_size);
|
let (st_vertices, rest) = map.split_at_mut(vertices_size);
|
||||||
let (st_indices, st_drawcalls) = rest.split_at_mut(indices_size);
|
let (st_indices, st_drawcalls) = rest.split_at_mut(indices_size);
|
||||||
|
|
@ -484,21 +480,21 @@ pub fn egui_pass(
|
||||||
name: Some("egui-draw-vertices".into()),
|
name: Some("egui-draw-vertices".into()),
|
||||||
size: vertices_size as u64,
|
size: vertices_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
let indices = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
|
let indices = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
|
||||||
name: Some("egui-draw-indices".into()),
|
name: Some("egui-draw-indices".into()),
|
||||||
size: indices_size as u64,
|
size: indices_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
let draw_calls = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
|
let draw_calls = rg.add_resource(GraphResourceDesc::Buffer(BufferDesc {
|
||||||
name: Some("egui-draw-draw_calls".into()),
|
name: Some("egui-draw-draw_calls".into()),
|
||||||
size: draw_calls_size as u64,
|
size: draw_calls_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDIRECT_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDIRECT_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -508,13 +504,14 @@ pub fn egui_pass(
|
||||||
name: Some("egui-draw-texture_ids".into()),
|
name: Some("egui-draw-texture_ids".into()),
|
||||||
size: (textures_indices.len() * size_of::<u32>()) as u64,
|
size: (textures_indices.len() * size_of::<u32>()) as u64,
|
||||||
usage: vk::BufferUsageFlags::STORAGE_BUFFER,
|
usage: vk::BufferUsageFlags::STORAGE_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::CpuToGpu,
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
{
|
{
|
||||||
let mut map = texture_ids.map()?;
|
let map = texture_ids
|
||||||
|
.map_mut()
|
||||||
|
.expect("texture id buffer should be device visible");
|
||||||
map.copy_from_slice(bytemuck::cast_slice(&textures_indices));
|
map.copy_from_slice(bytemuck::cast_slice(&textures_indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -528,7 +525,7 @@ pub fn egui_pass(
|
||||||
vk::DescriptorImageInfo {
|
vk::DescriptorImageInfo {
|
||||||
sampler: samplers.get_sampler(entry.as_sampler_desc()).unwrap(),
|
sampler: samplers.get_sampler(entry.as_sampler_desc()).unwrap(),
|
||||||
image_view: texture
|
image_view: texture
|
||||||
.get_view(ImageViewDesc {
|
.create_view(ImageViewDesc {
|
||||||
kind: vk::ImageViewType::TYPE_2D,
|
kind: vk::ImageViewType::TYPE_2D,
|
||||||
format: texture.format(),
|
format: texture.format(),
|
||||||
aspect: vk::ImageAspectFlags::COLOR,
|
aspect: vk::ImageAspectFlags::COLOR,
|
||||||
|
|
@ -536,14 +533,15 @@ pub fn egui_pass(
|
||||||
layer_range: (0..1).into(),
|
layer_range: (0..1).into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap()
|
||||||
|
.raw(),
|
||||||
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let uniform_info = vk::DescriptorBufferInfo {
|
let uniform_info = vk::DescriptorBufferInfo {
|
||||||
buffer: texture_ids.buffer(),
|
buffer: texture_ids.raw(),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
range: texture_ids.len(),
|
range: texture_ids.len(),
|
||||||
};
|
};
|
||||||
|
|
@ -609,8 +607,8 @@ pub fn egui_pass(
|
||||||
let target = ctx.get_image(target).unwrap();
|
let target = ctx.get_image(target).unwrap();
|
||||||
|
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.buffer(),
|
staging.raw(),
|
||||||
vertices.buffer(),
|
vertices.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: 0,
|
src_offset: 0,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -618,8 +616,8 @@ pub fn egui_pass(
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.buffer(),
|
staging.raw(),
|
||||||
indices.buffer(),
|
indices.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: vertices_size as u64,
|
src_offset: vertices_size as u64,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -627,8 +625,8 @@ pub fn egui_pass(
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.buffer(),
|
staging.raw(),
|
||||||
draw_calls.buffer(),
|
draw_calls.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: (vertices_size + indices_size) as u64,
|
src_offset: (vertices_size + indices_size) as u64,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -638,7 +636,7 @@ pub fn egui_pass(
|
||||||
|
|
||||||
let barriers = [
|
let barriers = [
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
vertices.handle(),
|
vertices.raw(),
|
||||||
0,
|
0,
|
||||||
vertices.len(),
|
vertices.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -646,7 +644,7 @@ pub fn egui_pass(
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
indices.handle(),
|
indices.raw(),
|
||||||
0,
|
0,
|
||||||
indices.len(),
|
indices.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -654,7 +652,7 @@ pub fn egui_pass(
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
draw_calls.handle(),
|
draw_calls.raw(),
|
||||||
0,
|
0,
|
||||||
draw_calls.len(),
|
draw_calls.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -671,12 +669,16 @@ pub fn egui_pass(
|
||||||
|
|
||||||
let color_attachment = &vk::RenderingAttachmentInfo::default()
|
let color_attachment = &vk::RenderingAttachmentInfo::default()
|
||||||
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
.image_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||||
.image_view(target.get_view(ImageViewDesc {
|
.image_view(
|
||||||
kind: vk::ImageViewType::TYPE_2D,
|
target
|
||||||
format: target.format(),
|
.create_view(ImageViewDesc {
|
||||||
aspect: vk::ImageAspectFlags::COLOR,
|
kind: vk::ImageViewType::TYPE_2D,
|
||||||
..Default::default()
|
format: target.format(),
|
||||||
})?)
|
aspect: vk::ImageAspectFlags::COLOR,
|
||||||
|
..Default::default()
|
||||||
|
})?
|
||||||
|
.raw(),
|
||||||
|
)
|
||||||
.load_op(vk::AttachmentLoadOp::LOAD)
|
.load_op(vk::AttachmentLoadOp::LOAD)
|
||||||
.store_op(vk::AttachmentStoreOp::STORE);
|
.store_op(vk::AttachmentStoreOp::STORE);
|
||||||
|
|
||||||
|
|
@ -700,8 +702,8 @@ pub fn egui_pass(
|
||||||
.height(target.height() as f32)]);
|
.height(target.height() as f32)]);
|
||||||
|
|
||||||
cmd.bind_pipeline(&pipeline);
|
cmd.bind_pipeline(&pipeline);
|
||||||
cmd.bind_indices(indices.buffer(), 0, vk::IndexType::UINT32);
|
cmd.bind_indices(indices.raw(), 0, vk::IndexType::UINT32);
|
||||||
cmd.bind_vertex_buffers(&[vertices.buffer()], &[0]);
|
cmd.bind_vertex_buffers(&[vertices.raw()], &[0]);
|
||||||
cmd.push_constants(
|
cmd.push_constants(
|
||||||
&pipeline_layout,
|
&pipeline_layout,
|
||||||
vk::ShaderStageFlags::VERTEX,
|
vk::ShaderStageFlags::VERTEX,
|
||||||
|
|
@ -716,7 +718,7 @@ pub fn egui_pass(
|
||||||
&[descriptor_set],
|
&[descriptor_set],
|
||||||
);
|
);
|
||||||
cmd.draw_indexed_indirect(
|
cmd.draw_indexed_indirect(
|
||||||
draw_calls.buffer(),
|
draw_calls.raw(),
|
||||||
0,
|
0,
|
||||||
num_draw_calls as u32,
|
num_draw_calls as u32,
|
||||||
size_of::<vk::DrawIndexedIndirectCommand>() as u32,
|
size_of::<vk::DrawIndexedIndirectCommand>() as u32,
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
use std::{
|
use std::{borrow::Cow, sync::Arc};
|
||||||
borrow::Cow,
|
|
||||||
collections::HashMap,
|
|
||||||
sync::{Arc, Weak},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
define_device_owned_handle,
|
device::{Allocation, AllocationStrategy, DeviceHandle, DeviceObject, QueueFlags},
|
||||||
device::{Allocation, DeviceHandle, DeviceObject, DeviceOwned, QueueFlags},
|
|
||||||
swapchain::Swapchain,
|
swapchain::Swapchain,
|
||||||
util::weak_vec::WeakVec,
|
util::weak_vec::WeakVec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Device;
|
use super::Device;
|
||||||
use ash::{prelude::*, vk};
|
use ash::vk;
|
||||||
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
|
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use vk_mem::Alloc;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ImageDesc {
|
pub struct ImageDesc {
|
||||||
|
|
@ -33,6 +27,7 @@ pub struct ImageDesc {
|
||||||
pub layout: vk::ImageLayout,
|
pub layout: vk::ImageLayout,
|
||||||
|
|
||||||
pub mem_location: gpu_allocator::MemoryLocation,
|
pub mem_location: gpu_allocator::MemoryLocation,
|
||||||
|
pub alloc_scheme: AllocationStrategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for ImageDesc {
|
impl std::hash::Hash for ImageDesc {
|
||||||
|
|
@ -87,6 +82,7 @@ impl<'a> std::fmt::Debug for ImageDesc {
|
||||||
.field("queue_families", &self.queue_families)
|
.field("queue_families", &self.queue_families)
|
||||||
.field("layout", &self.layout)
|
.field("layout", &self.layout)
|
||||||
.field("mem_location", &self.mem_location)
|
.field("mem_location", &self.mem_location)
|
||||||
|
.field("alloc_scheme", &self.alloc_scheme)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,6 +103,7 @@ impl Default for ImageDesc {
|
||||||
queue_families: QueueFlags::empty(),
|
queue_families: QueueFlags::empty(),
|
||||||
layout: vk::ImageLayout::UNDEFINED,
|
layout: vk::ImageLayout::UNDEFINED,
|
||||||
mem_location: gpu_allocator::MemoryLocation::Unknown,
|
mem_location: gpu_allocator::MemoryLocation::Unknown,
|
||||||
|
alloc_scheme: AllocationStrategy::AllocatorManaged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +165,10 @@ impl Image {
|
||||||
requirements,
|
requirements,
|
||||||
location: desc.mem_location,
|
location: desc.mem_location,
|
||||||
linear: desc.tiling == vk::ImageTiling::LINEAR,
|
linear: desc.tiling == vk::ImageTiling::LINEAR,
|
||||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
allocation_scheme: match desc.alloc_scheme {
|
||||||
|
AllocationStrategy::AllocatorManaged => AllocationScheme::GpuAllocatorManaged,
|
||||||
|
AllocationStrategy::Dedicated => AllocationScheme::DedicatedImage(image),
|
||||||
|
},
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
@ -316,6 +316,10 @@ impl Image {
|
||||||
|
|
||||||
Ok((image, requirements))
|
Ok((image, requirements))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn raw(&self) -> vk::Image {
|
||||||
|
self.image.image()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Image {}
|
impl Eq for Image {}
|
||||||
|
|
@ -359,35 +363,35 @@ impl Image {
|
||||||
self.image.allocation_mut()
|
self.image.allocation_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// technically, this ImageView belongs to the image and is managed by it.
|
// /// technically, this ImageView belongs to the image and is managed by it.
|
||||||
pub fn get_view(&self, desc: ImageViewDesc) -> VkResult<vk::ImageView> {
|
// pub fn get_view(&self, desc: ImageViewDesc) -> VkResult<vk::ImageView> {
|
||||||
use std::collections::hash_map::Entry::*;
|
// use std::collections::hash_map::Entry::*;
|
||||||
match self.views.lock().entry(desc.hash_eq_copy()) {
|
// match self.views.lock().entry(desc.hash_eq_copy()) {
|
||||||
Occupied(occupied) => Ok(*occupied.get()),
|
// Occupied(occupied) => Ok(*occupied.get()),
|
||||||
Vacant(vacant) => {
|
// Vacant(vacant) => {
|
||||||
let view = unsafe {
|
// let view = unsafe {
|
||||||
let create_info = vk::ImageViewCreateInfo::default()
|
// let create_info = vk::ImageViewCreateInfo::default()
|
||||||
.flags(desc.flags)
|
// .flags(desc.flags)
|
||||||
.image(self.image())
|
// .image(self.image())
|
||||||
.view_type(vk::ImageViewType::TYPE_2D)
|
// .view_type(vk::ImageViewType::TYPE_2D)
|
||||||
.format(desc.format)
|
// .format(desc.format)
|
||||||
.components(desc.components)
|
// .components(desc.components)
|
||||||
.subresource_range(
|
// .subresource_range(
|
||||||
vk::ImageSubresourceRange::default()
|
// vk::ImageSubresourceRange::default()
|
||||||
.aspect_mask(desc.aspect)
|
// .aspect_mask(desc.aspect)
|
||||||
.base_mip_level(desc.mip_range.0)
|
// .base_mip_level(desc.mip_range.0)
|
||||||
.level_count(desc.mip_range.count())
|
// .level_count(desc.mip_range.count())
|
||||||
.base_array_layer(desc.layer_range.0)
|
// .base_array_layer(desc.layer_range.0)
|
||||||
.layer_count(desc.layer_range.count()),
|
// .layer_count(desc.layer_range.count()),
|
||||||
);
|
// );
|
||||||
self.device().dev().create_image_view(&create_info, None)?
|
// self.device().dev().create_image_view(&create_info, None)?
|
||||||
};
|
// };
|
||||||
Ok(*vacant.insert(view))
|
// Ok(*vacant.insert(view))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn create_view(&self, desc: ImageViewDesc) -> crate::Result<ImageView> {
|
pub fn create_view(self: &Arc<Self>, mut desc: ImageViewDesc) -> crate::Result<ImageView> {
|
||||||
// validate
|
// validate
|
||||||
if !view_kind_compatible(self.desc.kind, desc.kind) {
|
if !view_kind_compatible(self.desc.kind, desc.kind) {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
|
|
@ -410,6 +414,10 @@ impl Image {
|
||||||
return Err(crate::Error::Unspecified);
|
return Err(crate::Error::Unspecified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if desc.format == vk::Format::UNDEFINED {
|
||||||
|
desc.format = self.desc.format;
|
||||||
|
}
|
||||||
|
|
||||||
let create_info = vk::ImageViewCreateInfo::default()
|
let create_info = vk::ImageViewCreateInfo::default()
|
||||||
.flags(desc.flags)
|
.flags(desc.flags)
|
||||||
.image(self.image())
|
.image(self.image())
|
||||||
|
|
@ -428,10 +436,16 @@ impl Image {
|
||||||
let device = self.image.device();
|
let device = self.image.device();
|
||||||
let view = unsafe { device.raw.create_image_view(&create_info, None)? };
|
let view = unsafe { device.raw.create_image_view(&create_info, None)? };
|
||||||
|
|
||||||
ImageView::construct(self.device().clone(), view, desc.name)
|
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 {}
|
||||||
|
|
||||||
fn view_kind_compatible(image_kind: vk::ImageType, view_kind: vk::ImageViewType) -> bool {
|
fn view_kind_compatible(image_kind: vk::ImageType, view_kind: vk::ImageViewType) -> bool {
|
||||||
use vk::ImageType as IT;
|
use vk::ImageType as IT;
|
||||||
use vk::ImageViewType as VT;
|
use vk::ImageViewType as VT;
|
||||||
|
|
@ -456,7 +470,19 @@ pub struct ImageViewDesc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageViewDesc {
|
impl ImageViewDesc {
|
||||||
pub fn hash_eq_copy(&self) -> Self {
|
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(crate) fn hash_eq_copy(&self) -> Self {
|
||||||
let &Self {
|
let &Self {
|
||||||
flags,
|
flags,
|
||||||
kind,
|
kind,
|
||||||
|
|
@ -561,6 +587,15 @@ pub struct ImageView {
|
||||||
image: Arc<Image>,
|
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 {
|
impl DeviceHandle for vk::ImageView {
|
||||||
unsafe fn destroy(&mut self, device: &Device) {
|
unsafe fn destroy(&mut self, device: &Device) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::OnceCell,
|
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
|
|
|
||||||
|
|
@ -1021,10 +1021,13 @@ impl Renderer2 {
|
||||||
surface: &swapchain::Surface,
|
surface: &swapchain::Surface,
|
||||||
cb: F,
|
cb: F,
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
let frame = surface.acquire_image().await?;
|
let Some(frame) = surface.acquire_image() else {
|
||||||
|
return Err(Error::SuboptimalSwapchain);
|
||||||
|
};
|
||||||
|
let (frame, _suboptimal) = frame.await?;
|
||||||
|
|
||||||
let mut rg = render_graph::RenderGraph::new();
|
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);
|
let out = cb(self, &mut rg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,15 @@ pub struct QueueInner {
|
||||||
pub(crate) lock: Mutex<()>,
|
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)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct QueueFamily {
|
pub struct QueueFamily {
|
||||||
pub index: u32,
|
pub index: u32,
|
||||||
|
|
|
||||||
|
|
@ -62,13 +62,11 @@ impl GraphResource {
|
||||||
discr.hash(&mut state);
|
discr.hash(&mut state);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
GraphResource::Framebuffer(swapchain_frame) => {
|
GraphResource::Framebuffer(swapchain_frame) => (swapchain_frame.raw()).hash(&mut state),
|
||||||
(swapchain_frame.handle()).hash(&mut state)
|
GraphResource::ImportedImage(image) => image.raw().hash(&mut state),
|
||||||
}
|
GraphResource::ImportedBuffer(buffer) => buffer.raw().hash(&mut state),
|
||||||
GraphResource::ImportedImage(image) => image.handle().hash(&mut state),
|
GraphResource::Image(image) => image.raw().hash(&mut state),
|
||||||
GraphResource::ImportedBuffer(buffer) => buffer.handle().hash(&mut state),
|
GraphResource::Buffer(buffer) => buffer.raw().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::ImageDesc(image_desc) => image_desc.hash(&mut state),
|
||||||
GraphResource::BufferDesc(buffer_desc) => buffer_desc.hash(&mut state),
|
GraphResource::BufferDesc(buffer_desc) => buffer_desc.hash(&mut state),
|
||||||
GraphResource::Default => {}
|
GraphResource::Default => {}
|
||||||
|
|
@ -486,7 +484,7 @@ impl RenderGraph {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ash::prelude::VkResult::Ok(())
|
crate::Result::Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let pool =
|
let pool =
|
||||||
|
|
@ -561,19 +559,19 @@ impl RenderGraph {
|
||||||
) {
|
) {
|
||||||
let barrier: Barrier = match res {
|
let barrier: Barrier = match res {
|
||||||
GraphResource::Framebuffer(arc) => {
|
GraphResource::Framebuffer(arc) => {
|
||||||
image_barrier(arc.handle(), arc.format(), from, to, None).into()
|
image_barrier(arc.raw(), arc.format(), from, to, None).into()
|
||||||
}
|
}
|
||||||
GraphResource::ImportedImage(arc) => {
|
GraphResource::ImportedImage(arc) => {
|
||||||
image_barrier(arc.handle(), arc.format(), from, to, None).into()
|
image_barrier(arc.raw(), arc.format(), from, to, None).into()
|
||||||
}
|
}
|
||||||
GraphResource::ImportedBuffer(arc) => {
|
GraphResource::ImportedBuffer(arc) => {
|
||||||
buffer_barrier(arc.handle(), 0, arc.len(), from, to, None).into()
|
buffer_barrier(arc.raw(), 0, arc.len(), from, to, None).into()
|
||||||
}
|
}
|
||||||
GraphResource::Image(image) => {
|
GraphResource::Image(image) => {
|
||||||
image_barrier(image.handle(), image.format(), from, to, None).into()
|
image_barrier(image.raw(), image.format(), from, to, None).into()
|
||||||
}
|
}
|
||||||
GraphResource::Buffer(buffer) => {
|
GraphResource::Buffer(buffer) => {
|
||||||
buffer_barrier(buffer.handle(), 0, buffer.len(), from, to, None).into()
|
buffer_barrier(buffer.raw(), 0, buffer.len(), from, to, None).into()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -1297,7 +1295,7 @@ pub fn clear_pass(rg: &mut RenderGraph, color: Rgba, target: GraphResourceId) {
|
||||||
let cmd = &ctx.cmd;
|
let cmd = &ctx.cmd;
|
||||||
|
|
||||||
cmd.clear_color_image(
|
cmd.clear_color_image(
|
||||||
target.handle(),
|
target.raw(),
|
||||||
target.format(),
|
target.format(),
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
color,
|
color,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use glam::{f32::Mat4, vec3};
|
use glam::{f32::Mat4, vec3};
|
||||||
|
use gpu_allocator::MemoryLocation;
|
||||||
|
|
||||||
pub use crate::egui_pass::{egui_pass, egui_pre_pass};
|
pub use crate::egui_pass::{egui_pass, egui_pre_pass};
|
||||||
|
|
||||||
|
|
@ -9,7 +10,7 @@ use crate::{
|
||||||
Result,
|
Result,
|
||||||
buffers::{Buffer, BufferDesc},
|
buffers::{Buffer, BufferDesc},
|
||||||
commands::{self, traits::CommandBufferExt},
|
commands::{self, traits::CommandBufferExt},
|
||||||
device::{Device, DeviceOwned},
|
device::Device,
|
||||||
images::ImageViewDesc,
|
images::ImageViewDesc,
|
||||||
pipeline,
|
pipeline,
|
||||||
render_graph::{
|
render_graph::{
|
||||||
|
|
@ -50,16 +51,15 @@ impl Wireframe {
|
||||||
name: Some("wireframe-staging".into()),
|
name: Some("wireframe-staging".into()),
|
||||||
size: staging_size as u64,
|
size: staging_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferHost,
|
mem_location: MemoryLocation::CpuToGpu,
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags::MAPPED
|
|
||||||
| vk_mem::AllocationCreateFlags::HOST_ACCESS_SEQUENTIAL_WRITE
|
|
||||||
| vk_mem::AllocationCreateFlags::STRATEGY_FIRST_FIT,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut map = staging.map()?;
|
let map = staging
|
||||||
|
.map_mut()
|
||||||
|
.expect("staging buffer should be host visible");
|
||||||
|
|
||||||
map[..positions_size].copy_from_slice(bytemuck::cast_slice(&positions));
|
map[..positions_size].copy_from_slice(bytemuck::cast_slice(&positions));
|
||||||
map[indices_offset..][..indices_size].copy_from_slice(bytemuck::cast_slice(&indices));
|
map[indices_offset..][..indices_size].copy_from_slice(bytemuck::cast_slice(&indices));
|
||||||
|
|
@ -72,7 +72,7 @@ impl Wireframe {
|
||||||
name: Some("wireframe-positions".into()),
|
name: Some("wireframe-positions".into()),
|
||||||
size: positions_size as u64,
|
size: positions_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -82,7 +82,7 @@ impl Wireframe {
|
||||||
name: Some("wireframe-indices".into()),
|
name: Some("wireframe-indices".into()),
|
||||||
size: indices_size as u64,
|
size: indices_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -92,7 +92,7 @@ impl Wireframe {
|
||||||
name: Some("wireframe-colors".into()),
|
name: Some("wireframe-colors".into()),
|
||||||
size: colors_size as u64,
|
size: colors_size as u64,
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
usage: vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
mem_usage: vk_mem::MemoryUsage::AutoPreferDevice,
|
mem_location: MemoryLocation::GpuOnly,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -102,8 +102,8 @@ impl Wireframe {
|
||||||
let cmd = pool.alloc()?;
|
let cmd = pool.alloc()?;
|
||||||
|
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.handle(),
|
staging.raw(),
|
||||||
positions.handle(),
|
positions.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: 0,
|
src_offset: 0,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -111,8 +111,8 @@ impl Wireframe {
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.handle(),
|
staging.raw(),
|
||||||
indices.handle(),
|
indices.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: indices_offset as u64,
|
src_offset: indices_offset as u64,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -120,8 +120,8 @@ impl Wireframe {
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
cmd.copy_buffers(
|
cmd.copy_buffers(
|
||||||
staging.handle(),
|
staging.raw(),
|
||||||
colors.handle(),
|
colors.raw(),
|
||||||
&[vk::BufferCopy {
|
&[vk::BufferCopy {
|
||||||
src_offset: colors_offset as u64,
|
src_offset: colors_offset as u64,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
|
|
@ -131,7 +131,7 @@ impl Wireframe {
|
||||||
|
|
||||||
let barriers = [
|
let barriers = [
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
positions.handle(),
|
positions.raw(),
|
||||||
0,
|
0,
|
||||||
positions.len(),
|
positions.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -139,7 +139,7 @@ impl Wireframe {
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
indices.handle(),
|
indices.raw(),
|
||||||
0,
|
0,
|
||||||
indices.len(),
|
indices.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -147,7 +147,7 @@ impl Wireframe {
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
buffer_barrier(
|
buffer_barrier(
|
||||||
colors.handle(),
|
colors.raw(),
|
||||||
0,
|
0,
|
||||||
colors.len(),
|
colors.len(),
|
||||||
Access::transfer_write(),
|
Access::transfer_write(),
|
||||||
|
|
@ -363,8 +363,8 @@ impl Wireframe {
|
||||||
.height(target.height() as f32)]);
|
.height(target.height() as f32)]);
|
||||||
|
|
||||||
cmd.bind_pipeline(&pipeline);
|
cmd.bind_pipeline(&pipeline);
|
||||||
cmd.bind_indices(indices.buffer(), 0, vk::IndexType::UINT32);
|
cmd.bind_indices(indices.raw(), 0, vk::IndexType::UINT32);
|
||||||
cmd.bind_vertex_buffers(&[positions.handle(), colors.handle()], &[0, 0]);
|
cmd.bind_vertex_buffers(&[positions.raw(), colors.raw()], &[0, 0]);
|
||||||
cmd.push_constants(
|
cmd.push_constants(
|
||||||
&layout,
|
&layout,
|
||||||
vk::ShaderStageFlags::VERTEX,
|
vk::ShaderStageFlags::VERTEX,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
marker::PhantomData,
|
ops::Deref,
|
||||||
sync::{
|
sync::{
|
||||||
Arc,
|
Arc,
|
||||||
atomic::{AtomicU32, AtomicU64, Ordering},
|
atomic::{AtomicU32, AtomicU64, Ordering},
|
||||||
|
|
@ -12,16 +12,14 @@ use ash::{
|
||||||
prelude::VkResult,
|
prelude::VkResult,
|
||||||
vk::{self, Handle},
|
vk::{self, Handle},
|
||||||
};
|
};
|
||||||
use parking_lot::{Mutex, RawMutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Instance, PhysicalDeviceInfo, Result, SurfaceCapabilities, define_device_owned_handle,
|
Instance, PhysicalDeviceInfo, Result, SurfaceCapabilities,
|
||||||
device::{Device, DeviceObject, DeviceOwned},
|
device::{Device, DeviceObject},
|
||||||
images,
|
images::{self, ImageViewDesc},
|
||||||
instance::InstanceInner,
|
sync::Fence,
|
||||||
sync::{self, Fence},
|
|
||||||
util::RawMutexGuard,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use derive_more::Debug;
|
use derive_more::Debug;
|
||||||
|
|
@ -274,6 +272,18 @@ impl Surface {
|
||||||
composite_alpha_mode,
|
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)]
|
#[derive(Debug)]
|
||||||
|
|
@ -302,7 +312,7 @@ pub struct Swapchain {
|
||||||
|
|
||||||
// Some of the swapchain operations require external synchronisation; this mutex allows `Swapchain` to be `Sync`.
|
// Some of the swapchain operations require external synchronisation; this mutex allows `Swapchain` to be `Sync`.
|
||||||
#[debug(skip)]
|
#[debug(skip)]
|
||||||
guard: parking_lot::RawMutex,
|
pub(crate) guard: parking_lot::Mutex<()>,
|
||||||
|
|
||||||
// for khr_present_id/khr_present_wait
|
// for khr_present_id/khr_present_wait
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|
@ -365,7 +375,7 @@ impl Swapchain {
|
||||||
.expect("swapchain extension not loaded");
|
.expect("swapchain extension not loaded");
|
||||||
|
|
||||||
let (swapchain, images) = {
|
let (swapchain, images) = {
|
||||||
let _lock = old_swapchain.as_ref().map(|old| old.lock());
|
let _lock = old_swapchain.as_ref().map(|old| old.guard.lock());
|
||||||
let old_swapchain = old_swapchain
|
let old_swapchain = old_swapchain
|
||||||
.map(|swp| *swp.swapchain)
|
.map(|swp| *swp.swapchain)
|
||||||
.unwrap_or(vk::SwapchainKHR::null());
|
.unwrap_or(vk::SwapchainKHR::null());
|
||||||
|
|
@ -467,7 +477,7 @@ impl Swapchain {
|
||||||
),
|
),
|
||||||
images,
|
images,
|
||||||
config,
|
config,
|
||||||
guard: <RawMutex as parking_lot::lock_api::RawMutex>::INIT,
|
guard: Mutex::new(()),
|
||||||
min_image_count: surface_caps.capabilities.min_image_count,
|
min_image_count: surface_caps.capabilities.min_image_count,
|
||||||
acquire_semaphores,
|
acquire_semaphores,
|
||||||
release_semaphores,
|
release_semaphores,
|
||||||
|
|
@ -485,11 +495,15 @@ impl Swapchain {
|
||||||
self.images.len() as u32
|
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
|
/// returns a future yielding the frame, and true if the swapchain is
|
||||||
/// suboptimal and should be recreated.
|
/// suboptimal and should be recreated.
|
||||||
fn acquire_image(
|
fn acquire_image(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
) -> impl std::future::Future<Output = crate::Result<(SwapchainFrame, bool)>> {
|
) -> impl std::future::Future<Output = crate::Result<(SwapchainImage, bool)>> {
|
||||||
let frame = self
|
let frame = self
|
||||||
.current_frame
|
.current_frame
|
||||||
.try_update(Ordering::Release, Ordering::Relaxed, |i| {
|
.try_update(Ordering::Release, Ordering::Relaxed, |i| {
|
||||||
|
|
@ -507,28 +521,34 @@ impl Swapchain {
|
||||||
// spawn on threadpool because it might block.
|
// spawn on threadpool because it might block.
|
||||||
let (idx, suboptimal) = smol::unblock({
|
let (idx, suboptimal) = smol::unblock({
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
|
let fence = fence.raw();
|
||||||
move || unsafe {
|
move || unsafe {
|
||||||
this.with_locked(|swapchain| {
|
this.with_locked(|swapchain| {
|
||||||
this.functor
|
this.functor
|
||||||
.acquire_next_image(swapchain, u64::MAX, acquire, fence.raw())
|
.acquire_next_image(swapchain.raw(), u64::MAX, acquire, fence)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.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.
|
// wait for image to become available.
|
||||||
fence.into_future().await;
|
fence.into_future().await;
|
||||||
|
|
||||||
let idx = idx as usize;
|
|
||||||
let image = self.images[idx].clone();
|
|
||||||
let view = self.image_views[idx];
|
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
SwapchainFrame {
|
SwapchainImage {
|
||||||
index: idx as u32,
|
index: idx as u32,
|
||||||
swapchain: self.clone(),
|
swapchain: self,
|
||||||
format: self.config.format,
|
|
||||||
image,
|
|
||||||
view,
|
view,
|
||||||
acquire,
|
acquire,
|
||||||
release,
|
release,
|
||||||
|
|
@ -538,31 +558,36 @@ impl Swapchain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present(&self, frame: SwapchainFrame, wait: Option<vk::Semaphore>) -> Result<()> {
|
/// # Safety
|
||||||
let swpchain = self.lock();
|
/// The caller must ensure that the provided index corresponds to an image
|
||||||
let queue = self.device().present_queue().lock();
|
/// that is currently acquired and not yet presented.
|
||||||
|
unsafe fn present(&self, index: u32, wait: Option<vk::Semaphore>) -> Result<()> {
|
||||||
|
let _lock = self.guard.lock();
|
||||||
|
|
||||||
let wait_semaphores = wait.as_slice();
|
let wait_semaphores = wait.as_slice();
|
||||||
|
|
||||||
// TODO: make this optional for devices with no support for present_wait/present_id
|
|
||||||
// let present_id = self
|
|
||||||
// .present_id
|
|
||||||
// .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
|
||||||
// let mut present_id =
|
|
||||||
// vk::PresentIdKHR::default().present_ids(core::slice::from_ref(&present_id));
|
|
||||||
|
|
||||||
let present_info = vk::PresentInfoKHR::default()
|
let present_info = vk::PresentInfoKHR::default()
|
||||||
.image_indices(core::slice::from_ref(&frame.index))
|
.image_indices(core::slice::from_ref(&index))
|
||||||
.swapchains(core::slice::from_ref(&swpchain))
|
.swapchains(core::slice::from_ref(&*self.swapchain))
|
||||||
.wait_semaphores(wait_semaphores);
|
.wait_semaphores(wait_semaphores);
|
||||||
//.push_next(&mut present_id)
|
|
||||||
|
|
||||||
// call winits pre_present_notify here
|
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
|
||||||
|
// .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
// let mut present_id =
|
||||||
|
// vk::PresentIdKHR::default().present_ids(core::slice::from_ref(&present_id));
|
||||||
|
|
||||||
unsafe {
|
//.push_next(&mut present_id)
|
||||||
self.functor.queue_present(*queue, &present_info)?;
|
|
||||||
}
|
// call winits pre_present_notify here
|
||||||
Ok(())
|
|
||||||
|
unsafe {
|
||||||
|
self.functor.queue_present(queue.raw(), &present_info)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
|
@ -615,6 +640,41 @@ impl Swapchain {
|
||||||
}
|
}
|
||||||
static SWAPCHAIN_COUNT: AtomicU64 = AtomicU64::new(0);
|
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)]
|
#[derive(Debug)]
|
||||||
#[must_use = "This struct represents an acquired image from the swapchain and
|
#[must_use = "This struct represents an acquired image from the swapchain and
|
||||||
must be presented in order to free resources on the device."]
|
must be presented in order to free resources on the device."]
|
||||||
|
|
@ -637,7 +697,8 @@ impl PartialEq for SwapchainFrame {
|
||||||
|
|
||||||
impl SwapchainFrame {
|
impl SwapchainFrame {
|
||||||
pub fn present(self, wait: Option<vk::Semaphore>) -> crate::Result<()> {
|
pub fn present(self, wait: Option<vk::Semaphore>) -> crate::Result<()> {
|
||||||
self.swapchain.clone().present(self, wait)
|
// 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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -678,19 +739,9 @@ pub struct SwapchainConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Swapchain {
|
impl Swapchain {
|
||||||
pub fn lock(&self) -> RawMutexGuard<'_, vk::SwapchainKHR> {
|
pub fn with_locked<T, F: FnOnce(&Self) -> T>(&self, f: F) -> T {
|
||||||
use parking_lot::lock_api::RawMutex;
|
let _lock = self.guard.lock();
|
||||||
self.guard.lock();
|
f(self)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,15 @@ use std::borrow::Cow;
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::ManuallyDrop,
|
|
||||||
sync::{Arc, atomic::AtomicU32},
|
sync::{Arc, atomic::AtomicU32},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::device::{DeviceObject, DeviceOwned, Pool, PoolObject, Pooled};
|
use crate::device::{DeviceObject, Pool, PoolObject, Pooled};
|
||||||
use crate::{Result, device::DeviceInner};
|
use crate::{Result, device::DeviceInner};
|
||||||
|
|
||||||
use super::Device;
|
use super::Device;
|
||||||
use ash::{prelude::*, vk};
|
use ash::{prelude::VkResult, vk};
|
||||||
use crossbeam::channel::{Receiver, Sender};
|
use crossbeam::channel::{Receiver, Sender};
|
||||||
|
|
||||||
type Message = (SyncPrimitive, std::task::Waker);
|
type Message = (SyncPrimitive, std::task::Waker);
|
||||||
|
|
@ -212,7 +211,7 @@ impl Fence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_on(&self, timeout: Option<u64>) -> Result<()> {
|
pub fn wait_on(&self, timeout: Option<u64>) -> VkResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device().raw.wait_for_fences(
|
self.device().raw.wait_for_fences(
|
||||||
core::slice::from_ref(&self.raw()),
|
core::slice::from_ref(&self.raw()),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue