use super::DescriptorSetArc;
use super::DescriptorSetElementKey;
use super::DescriptorSetWriteSet;
use crate::resources::descriptor_sets::descriptor_write_set::{
DescriptorSetWriteElementBufferData, DescriptorSetWriteElementImageValue,
};
use crate::resources::descriptor_sets::{
DescriptorSetAllocator, DescriptorSetWriteElementBufferDataBufferRef,
};
use crate::resources::resource_lookup::{DescriptorSetLayoutResource, ImageViewResource};
use crate::resources::ResourceArc;
use crate::BufferResource;
use rafx_api::{RafxCommandBuffer, RafxResult};
use std::fmt::Formatter;
pub struct DynDescriptorSet {
descriptor_set_layout: ResourceArc<DescriptorSetLayoutResource>,
descriptor_set: DescriptorSetArc,
write_set: DescriptorSetWriteSet,
pending_write_set: DescriptorSetWriteSet,
has_been_flushed: bool,
}
impl std::fmt::Debug for DynDescriptorSet {
fn fmt(
&self,
f: &mut Formatter<'_>,
) -> std::fmt::Result {
f.debug_struct("DynDescriptorSet")
.field("descriptor_set", &self.descriptor_set)
.finish()
}
}
impl Drop for DynDescriptorSet {
fn drop(&mut self) {
if !self.has_been_flushed {
panic!("A descriptor set was dropped without being flushed");
}
}
}
impl DynDescriptorSet {
pub(super) fn new(
descriptor_set_layout: &ResourceArc<DescriptorSetLayoutResource>,
descriptor_set: DescriptorSetArc,
write_set: DescriptorSetWriteSet,
) -> Self {
DynDescriptorSet {
descriptor_set_layout: descriptor_set_layout.clone(),
descriptor_set,
write_set,
pending_write_set: Default::default(),
has_been_flushed: false,
}
}
pub fn descriptor_set(&self) -> &DescriptorSetArc {
&self.descriptor_set
}
pub fn bind(
&self,
command_buffer: &RafxCommandBuffer,
) -> RafxResult<()> {
self.descriptor_set.bind(command_buffer)
}
pub fn flush(
&mut self,
descriptor_set_allocator: &mut DescriptorSetAllocator,
) -> RafxResult<()> {
if !self.pending_write_set.elements.is_empty() {
let mut pending_write_set = Default::default();
std::mem::swap(&mut pending_write_set, &mut self.pending_write_set);
self.write_set.copy_from(&pending_write_set);
let new_descriptor_set = descriptor_set_allocator.create_descriptor_set_with_writes(
&self.descriptor_set_layout,
pending_write_set,
)?;
log::trace!(
"DynDescriptorSet::flush {:?} -> {:?}",
self.descriptor_set,
new_descriptor_set
);
self.descriptor_set = new_descriptor_set;
}
self.has_been_flushed = true;
Ok(())
}
pub fn set_image(
&mut self,
binding_index: u32,
image_view: &ResourceArc<ImageViewResource>,
) {
self.set_image_array_element(
binding_index,
0,
DescriptorSetWriteElementImageValue::Resource(image_view.clone()),
)
}
pub fn set_images(
&mut self,
binding_index: u32,
image_views: &[Option<&ResourceArc<ImageViewResource>>],
) {
for (index, image_view) in image_views.iter().enumerate() {
if let Some(image_view) = image_view.as_ref() {
self.set_image_array_element(
binding_index,
index,
DescriptorSetWriteElementImageValue::Resource((*image_view).clone()),
)
}
}
}
pub fn set_image_at_index(
&mut self,
binding_index: u32,
array_index: usize,
image_view: &ResourceArc<ImageViewResource>,
) {
self.set_image_array_element(
binding_index,
array_index,
DescriptorSetWriteElementImageValue::Resource(image_view.clone()),
)
}
fn set_image_array_element(
&mut self,
binding_index: u32,
array_index: usize,
image_view: DescriptorSetWriteElementImageValue,
) {
let key = DescriptorSetElementKey {
dst_binding: binding_index,
};
if let Some(element) = self.write_set.elements.get_mut(&key) {
let what_to_bind = super::what_to_bind(element);
if what_to_bind.bind_images {
if let Some(element_image) = element.image_info.get_mut(array_index) {
element_image.image_view = Some(image_view);
self.pending_write_set.elements.insert(key, element.clone());
} else {
log::warn!("Tried to set image index {} but it did not exist. The image array is {} elements long.", array_index, element.image_info.len());
}
} else {
}
} else {
log::warn!("Tried to set image on a binding index that does not exist");
}
}
pub fn set_buffer(
&mut self,
binding_index: u32,
data: &ResourceArc<BufferResource>,
) {
self.set_buffer_array_element(binding_index, 0, data)
}
pub fn set_buffer_at_index(
&mut self,
binding_index: u32,
array_index: usize,
data: &ResourceArc<BufferResource>,
) {
self.set_buffer_array_element(binding_index, array_index, data)
}
fn set_buffer_array_element(
&mut self,
binding_index: u32,
array_index: usize,
buffer: &ResourceArc<BufferResource>,
) {
let key = DescriptorSetElementKey {
dst_binding: binding_index,
};
if let Some(element) = self.write_set.elements.get_mut(&key) {
let what_to_bind = super::what_to_bind(element);
if what_to_bind.bind_buffers {
if let Some(element_buffer) = element.buffer_info.get_mut(array_index) {
element_buffer.buffer = Some(DescriptorSetWriteElementBufferData::BufferRef(
DescriptorSetWriteElementBufferDataBufferRef {
buffer: buffer.clone(),
offset: None,
size: None,
},
));
self.pending_write_set.elements.insert(key, element.clone());
} else {
log::warn!("Tried to set buffer index {} but it did not exist. The image array is {} elements long.", array_index, element.buffer_info.len());
}
} else {
}
} else {
log::warn!("Tried to set image on a binding index that does not exist");
}
}
pub fn set_buffer_data<T: Copy + 'static>(
&mut self,
binding_index: u32,
data: &T,
) {
self.set_buffer_data_array_element(binding_index, 0, data)
}
pub fn set_buffer_data_at_index<T: Copy + 'static>(
&mut self,
binding_index: u32,
array_index: usize,
data: &T,
) {
self.set_buffer_data_array_element(binding_index, array_index, data)
}
fn set_buffer_data_array_element<T: Copy + 'static>(
&mut self,
binding_index: u32,
array_index: usize,
data: &T,
) {
let key = DescriptorSetElementKey {
dst_binding: binding_index,
};
if let Some(element) = self.write_set.elements.get_mut(&key) {
let what_to_bind = super::what_to_bind(element);
if what_to_bind.bind_buffers {
let data = rafx_base::memory::any_as_bytes(data).into();
if let Some(element_buffer) = element.buffer_info.get_mut(array_index) {
element_buffer.buffer = Some(DescriptorSetWriteElementBufferData::Data(data));
self.pending_write_set.elements.insert(key, element.clone());
} else {
log::warn!("Tried to set buffer data for index {} but it did not exist. The buffer array is {} elements long.", array_index, element.buffer_info.len());
}
} else {
}
} else {
log::warn!("Tried to set buffer data on a binding index that does not exist");
}
}
}