use anyhow::Result;
use ash::vk;
use crate::{BufferView, Error, ImageView, PhysicalResourceBindings, Sampler, VirtualResource};
use crate::descriptor::descriptor_set::{
DescriptorBinding, DescriptorBufferInfo, DescriptorContents, DescriptorImageInfo,
DescriptorSetBinding,
};
use crate::graph::physical_resource::PhysicalResource;
#[cfg(feature = "shader-reflection")]
use crate::pipeline::shader_reflection::ReflectionInfo;
use crate::raytracing::acceleration_structure::AccelerationStructure;
#[cfg(feature = "shader-reflection")]
#[derive(Debug)]
pub(crate) struct DescriptorSetBuilder<'a> {
inner: DescriptorSetBinding,
#[allow(dead_code)]
reflection: Option<&'a ReflectionInfo>,
}
#[cfg(not(feature = "shader-reflection"))]
pub struct DescriptorSetBuilder<'a> {
inner: DescriptorSetBinding,
_phantom: PhantomData<&'a ()>,
}
impl<'r> Default for DescriptorSetBuilder<'r> {
fn default() -> Self {
Self {
inner: DescriptorSetBinding {
pool: vk::DescriptorPool::null(),
bindings: vec![],
layout: vk::DescriptorSetLayout::null(),
},
#[cfg(feature = "shader-reflection")]
reflection: None,
#[cfg(not(feature = "shader-reflection"))]
_phantom: PhantomData::default(),
}
}
}
impl<'r> DescriptorSetBuilder<'r> {
pub fn new() -> Self {
Self::default()
}
#[cfg(feature = "shader-reflection")]
#[allow(dead_code)]
pub fn with_reflection(info: &'r ReflectionInfo) -> Self {
Self {
inner: DescriptorSetBinding {
pool: vk::DescriptorPool::null(),
bindings: vec![],
layout: vk::DescriptorSetLayout::null(),
},
reflection: Some(info),
}
}
pub fn resolve_and_bind_sampled_image(
&mut self,
binding: u32,
resource: &VirtualResource,
sampler: &Sampler,
bindings: &PhysicalResourceBindings,
) -> Result<()> {
if let Some(PhysicalResource::Image(image)) = bindings.resolve(resource) {
self.bind_sampled_image(binding, image, sampler);
Ok(())
} else {
Err(Error::NoResourceBound(resource.uid().to_owned()).into())
}
}
pub fn bind_sampled_image(&mut self, binding: u32, image: &ImageView, sampler: &Sampler) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptors: vec![DescriptorContents::Image(DescriptorImageInfo {
sampler: unsafe { sampler.handle() },
view: image.clone(),
layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
})],
});
}
#[cfg(feature = "shader-reflection")]
#[allow(dead_code)]
pub fn bind_named_sampled_image(
&mut self,
name: &str,
image: &ImageView,
sampler: &Sampler,
) -> Result<()> {
let Some(info) = self.reflection else { return Err(Error::NoReflectionInformation.into()); };
let binding = info
.bindings
.get(name)
.ok_or_else(|| Error::NoBinding(name.to_string()))?;
self.bind_sampled_image(binding.binding, image, sampler);
Ok(())
}
pub fn bind_uniform_buffer(&mut self, binding: u32, buffer: &BufferView) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptors: vec![DescriptorContents::Buffer(DescriptorBufferInfo {
buffer: *buffer,
})],
});
}
#[cfg(feature = "shader-reflection")]
#[allow(dead_code)]
pub fn bind_named_uniform_buffer(&mut self, name: &str, buffer: &BufferView) -> Result<()> {
let Some(info) = self.reflection else { return Err(Error::NoReflectionInformation.into()); };
let binding = info
.bindings
.get(name)
.ok_or_else(|| Error::NoBinding(name.to_string()))?;
self.bind_uniform_buffer(binding.binding, buffer);
Ok(())
}
pub fn bind_storage_buffer(&mut self, binding: u32, buffer: &BufferView) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::STORAGE_BUFFER,
descriptors: vec![DescriptorContents::Buffer(DescriptorBufferInfo {
buffer: *buffer,
})],
})
}
pub fn bind_storage_image(&mut self, binding: u32, image: &ImageView) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::STORAGE_IMAGE,
descriptors: vec![DescriptorContents::Image(DescriptorImageInfo {
sampler: vk::Sampler::null(),
view: image.clone(),
layout: vk::ImageLayout::GENERAL,
})],
})
}
pub fn resolve_and_bind_storage_image(
&mut self,
binding: u32,
resource: &VirtualResource,
bindings: &PhysicalResourceBindings,
) -> Result<()> {
if let Some(PhysicalResource::Image(image)) = bindings.resolve(resource) {
self.bind_storage_image(binding, image);
Ok(())
} else {
Err(Error::NoResourceBound(resource.uid().to_owned()).into())
}
}
pub fn bind_acceleration_structure(&mut self, binding: u32, accel: &AccelerationStructure) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::ACCELERATION_STRUCTURE_KHR,
descriptors: vec![DescriptorContents::AccelerationStructure(unsafe { accel.handle() })],
})
}
pub fn build(self) -> DescriptorSetBinding {
self.inner
}
}