Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 63 additions & 9 deletions src/command_buffer/incomplete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use crate::{
VirtualResource,
};

use super::DescriptorState;

impl<'q, D: ExecutionDomain, A: Allocator> IncompleteCmdBuffer<'q, A>
for IncompleteCommandBuffer<'q, D, A>
{
Expand Down Expand Up @@ -123,6 +125,27 @@ impl<D: ExecutionDomain, A: Allocator> IncompleteCommandBuffer<'_, D, A> {
Ok(())
}

fn set_descriptor_set(
&mut self,
set: u32,
descriptor_set: Arc<crate::DescriptorSet>,
) -> Result<()> {
if self.current_descriptor_sets.is_none() {
self.current_descriptor_sets = Some(HashMap::new());
}

match self.current_descriptor_sets.as_mut().unwrap().entry(set) {
Entry::Occupied(mut entry) => {
*entry.get_mut() = DescriptorState::DescriptorSet(descriptor_set.clone());
}
Entry::Vacant(entry) => {
entry.insert(DescriptorState::DescriptorSet(descriptor_set.clone()));
}
};
self.descriptor_state_needs_update = true;
Ok(())
}

/// Modify the descriptor set state at a given set binding.
/// # Errors
/// * Fails if the supplied callback fails.
Expand All @@ -137,12 +160,20 @@ impl<D: ExecutionDomain, A: Allocator> IncompleteCommandBuffer<'_, D, A> {

match self.current_descriptor_sets.as_mut().unwrap().entry(set) {
Entry::Occupied(mut entry) => {
f(entry.get_mut())?;
match entry.get_mut() {
DescriptorState::Builder(ref mut builder) => f(builder)?,
entry => {
// replace descriptor set with builder
let mut builder = DescriptorSetBuilder::new();
f(&mut builder)?;
*entry = DescriptorState::Builder(builder);
},
}
}
Entry::Vacant(entry) => {
let mut builder = DescriptorSetBuilder::new();
f(&mut builder)?;
entry.insert(builder);
entry.insert(DescriptorState::Builder(builder));
}
};
self.descriptor_state_needs_update = true;
Expand All @@ -160,13 +191,20 @@ impl<D: ExecutionDomain, A: Allocator> IncompleteCommandBuffer<'_, D, A> {
}

let cache = self.descriptor_cache.clone();
for (index, builder) in self.current_descriptor_sets.take().unwrap() {
let mut info = builder.build();
info.layout = *self.current_set_layouts.get(index as usize).unwrap();
cache.with_descriptor_set(info, |set| {
self.bind_descriptor_set(index, set)?;
Ok(())
})?;
for (index, state) in self.current_descriptor_sets.take().unwrap() {
match state {
DescriptorState::Builder(builder) => {
let mut info = builder.build();
info.layout = *self.current_set_layouts.get(index as usize).unwrap();
cache.with_descriptor_set(info, |set| {
self.bind_descriptor_set(index, set)?;
Ok(())
})?;
},
DescriptorState::DescriptorSet(set) => {
self.bind_descriptor_set(index, &set)?;
}
}
}

// We updated all our descriptor sets, were good now.
Expand Down Expand Up @@ -299,6 +337,22 @@ impl<D: ExecutionDomain, A: Allocator> IncompleteCommandBuffer<'_, D, A> {
Ok(self)
}

/// Bind a [`BindlessPool`](crate::resouce::bindless::BindlessPool)
pub fn bind_bindless_pool<R>(
mut self,
index: u32,
bindless_pool: &crate::bindless::BindlessPool<R>
) -> Result<Self>
where
R: crate::bindless::BindlessResource
{
bindless_pool.with(|p| {
self.set_descriptor_set(index, p.descriptor_set.clone())
})?;

Ok(self)
}

/// Binds a new descriptor with type [`vk::DescriptorType::UNIFORM_BUFFER`].
/// This binding is not actually flushed to the command buffer until the next draw or dispatch call.
/// # Errors
Expand Down
11 changes: 9 additions & 2 deletions src/command_buffer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use std::collections::HashMap;
use std::marker::PhantomData;
use std::sync::MutexGuard;
use std::sync::{MutexGuard, Arc};

use anyhow::Result;
use ash::vk;
Expand Down Expand Up @@ -57,6 +57,13 @@ pub struct CommandBuffer<D: ExecutionDomain> {
_domain: PhantomData<D>,
}

#[derive(Derivative)]
#[derivative(Debug)]
enum DescriptorState {
Builder(DescriptorSetBuilder<'static>),
DescriptorSet(Arc<crate::DescriptorSet>),
}

/// This struct represents an incomplete command buffer.
/// This is a command buffer that has not been finished yet with [`IncompleteCommandBuffer::finish()`](crate::IncompleteCommandBuffer::finish).
/// Calling this method will turn it into an immutable command buffer which can then be submitted
Expand Down Expand Up @@ -96,7 +103,7 @@ pub struct IncompleteCommandBuffer<'q, D: ExecutionDomain, A: Allocator = Defaul
current_bindpoint: vk::PipelineBindPoint,
current_rendering_state: Option<PipelineRenderingInfo>,
current_render_area: vk::Rect2D,
current_descriptor_sets: Option<HashMap<u32, DescriptorSetBuilder<'static>>>,
current_descriptor_sets: Option<HashMap<u32, DescriptorState>>,
descriptor_state_needs_update: bool,
current_sbt_regions: Option<[vk::StridedDeviceAddressRegionKHR; 4]>,
// TODO: Only update disturbed descriptor sets
Expand Down
47 changes: 27 additions & 20 deletions src/descriptor/descriptor_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,30 @@ pub struct DescriptorSet {
pub(crate) handle: vk::DescriptorSet,
}

impl DescriptorSet {
pub(crate) fn new_uninitialized(device: Device, layout: vk::DescriptorSetLayout, pool: vk::DescriptorPool) -> Result<Self> {
let info = vk::DescriptorSetAllocateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
p_next: std::ptr::null(),
descriptor_pool: pool,
descriptor_set_count: 1,
p_set_layouts: &layout as *const _,
};
let set = unsafe { device.allocate_descriptor_sets(&info) }?
.first()
.cloned()
.unwrap();
#[cfg(feature = "log-objects")]
trace!("Created new VkDescriptorSet {set:p}");

Ok(DescriptorSet {
device,
pool: pool,
handle: set,
})
}
}

fn binding_image_info(binding: &DescriptorBinding) -> Vec<vk::DescriptorImageInfo> {
binding
.descriptors
Expand Down Expand Up @@ -120,26 +144,13 @@ impl Resource for DescriptorSet {
fn create(device: Device, key: &Self::Key, _: Self::ExtraParams<'_>) -> Result<Self>
where
Self: Sized, {
let info = vk::DescriptorSetAllocateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
p_next: std::ptr::null(),
descriptor_pool: key.pool,
descriptor_set_count: 1,
p_set_layouts: &key.layout,
};
let set = unsafe { device.allocate_descriptor_sets(&info) }?
.first()
.cloned()
.unwrap();
#[cfg(feature = "log-objects")]
trace!("Created new VkDescriptorSet {set:p}");

let descriptor_set = DescriptorSet::new_uninitialized(device.clone(), key.layout, key.pool)?;
let writes = key
.bindings
.iter()
.map(|binding| {
let mut write = WriteDescriptorSet {
set,
set: descriptor_set.handle,
binding: binding.binding,
array_element: 0,
count: binding.descriptors.len() as u32,
Expand Down Expand Up @@ -226,11 +237,7 @@ impl Resource for DescriptorSet {
device.update_descriptor_sets(vk_writes.as_slice(), &[]);
}

Ok(DescriptorSet {
device,
pool: key.pool,
handle: set,
})
Ok(descriptor_set)
}
}

Expand Down
Loading