Skip to content

Commit

Permalink
add: experimental descriptor indexing support
Browse files Browse the repository at this point in the history
  • Loading branch information
NotAPenguin0 committed Jul 13, 2023
1 parent 6cac4ee commit a49d400
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
29 changes: 22 additions & 7 deletions src/command_buffer/incomplete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ use std::sync::{Arc, MutexGuard};
use anyhow::{anyhow, ensure, Result};
use ash::vk;

use crate::{
Allocator, BufferView, DebugMessenger, DescriptorCache, DescriptorSet, Device, ImageView,
IncompleteCmdBuffer, PhysicalResourceBindings, PipelineCache, PipelineStage, Sampler,
VirtualResource,
};
use crate::command_buffer::{CommandBuffer, IncompleteCommandBuffer};
use crate::command_buffer::state::{RenderingAttachmentInfo, RenderingInfo};
use crate::command_buffer::{CommandBuffer, IncompleteCommandBuffer};
use crate::core::queue::Queue;
use crate::descriptor::builder::DescriptorSetBuilder;
use crate::pipeline::create_info::PipelineRenderingInfo;
use crate::query_pool::{QueryPool, ScopedQuery, TimestampQuery};
use crate::raytracing::acceleration_structure::AccelerationStructure;
use crate::sync::domain::ExecutionDomain;
use crate::{
Allocator, BufferView, DebugMessenger, DescriptorCache, DescriptorSet, Device, ImageView,
IncompleteCmdBuffer, PhysicalResourceBindings, PipelineCache, PipelineStage, Sampler,
VirtualResource,
};

impl<'q, D: ExecutionDomain, A: Allocator> IncompleteCmdBuffer<'q, A>
for IncompleteCommandBuffer<'q, D, A>
for IncompleteCommandBuffer<'q, D, A>
{
type Domain = D;

Expand Down Expand Up @@ -284,6 +284,21 @@ impl<D: ExecutionDomain, A: Allocator> IncompleteCommandBuffer<'_, D, A> {
Ok(self)
}

/// Bind an entire array of sampled images using the same sampler.
pub fn bind_sampled_image_array(
mut self,
set: u32,
binding: u32,
images: &[ImageView],
sampler: &Sampler,
) -> Result<Self> {
self.modify_descriptor_set(set, |builder| {
builder.bind_sampled_image_array(binding, images, sampler);
Ok(())
})?;
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
1 change: 1 addition & 0 deletions src/core/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ impl Device {
features.pipeline_statistics_query = vk::TRUE;
features_1_2.buffer_device_address = vk::TRUE;
features_1_2.host_query_reset = vk::TRUE;
features_1_2.descriptor_indexing = vk::TRUE;
features_1_3.synchronization2 = vk::TRUE;
features_1_3.dynamic_rendering = vk::TRUE;
features_1_3.maintenance4 = vk::TRUE;
Expand Down
15 changes: 15 additions & 0 deletions src/descriptor/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ impl<'r> DescriptorSetBuilder<'r> {
});
}

/// Bind an entire array of sampled images using the same sampler.
pub fn bind_sampled_image_array(&mut self, binding: u32, images: &[ImageView], sampler: &Sampler) {
self.inner.bindings.push(DescriptorBinding {
binding,
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptors: images.iter().map(|image| {
DescriptorContents::Image(DescriptorImageInfo {
sampler: unsafe { sampler.handle() },
view: image.clone(),
layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL
})
}).collect()
});
}

/// Bind an image view to the given binding as a [`vk::DescriptorType::COMBINED_IMAGE_SAMPLER`].
/// Uses the reflection information provided at construction to look up the correct binding slot by its name
/// defined in the shader.
Expand Down
10 changes: 10 additions & 0 deletions src/pipeline/set_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct DescriptorSetLayoutCreateInfo {
/// Whether this descriptor set layout is persistent. Should only be true if the pipeline layout
/// this belongs to is also persistent.
pub persistent: bool,
/// The binding flags for each binding, these are set separately because they go in a separate vulkan struct.
pub flags: Vec<vk::DescriptorBindingFlags>,
}

impl ResourceKey for DescriptorSetLayoutCreateInfo {
Expand All @@ -50,8 +52,16 @@ impl Resource for DescriptorSetLayout {
const MAX_TIME_TO_LIVE: u32 = 8;

fn create(device: Device, key: &Self::Key, _: Self::ExtraParams<'_>) -> Result<Self> {
let mut flags = vk::DescriptorSetLayoutBindingFlagsCreateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
p_next: std::ptr::null(),
binding_count: key.bindings.len() as u32,
p_binding_flags: key.flags.as_ptr(),
};

let info = vk::DescriptorSetLayoutCreateInfo::builder()
.bindings(key.bindings.as_slice())
.push_next(&mut flags)
.build();
let handle = unsafe { device.create_descriptor_set_layout(&info, None)? };
#[cfg(feature = "log-objects")]
Expand Down
16 changes: 12 additions & 4 deletions src/pipeline/shader_reflection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub(crate) struct BindingInfo {
pub stage: vk::ShaderStageFlags,
pub count: u32,
pub ty: vk::DescriptorType,
pub flags: vk::DescriptorBindingFlags,
}

/// Stores reflection information about a pipeline. Can be used to derive a pipeline layout
Expand Down Expand Up @@ -76,14 +77,14 @@ fn find_sampled_images(
let set = ast.get_decoration(image.id, Decoration::DescriptorSet)?;
let ty = ast.get_type(image.type_id)?;
let Type::SampledImage { array, .. } = ty else { unimplemented!() };
let count = if !array.is_empty() {
let (count, flags) = if !array.is_empty() {
if array[0] == 0 {
4096 // Max unbounded array size. If this is ever exceeded, I'll fix it.
(4096, vk::DescriptorBindingFlags::PARTIALLY_BOUND)
} else {
array[0]
(array[0], vk::DescriptorBindingFlags::PARTIALLY_BOUND)
}
} else {
1
(1, vk::DescriptorBindingFlags::empty())
};

info.bindings.insert(
Expand All @@ -94,6 +95,7 @@ fn find_sampled_images(
stage,
count,
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
flags,
},
);
}
Expand All @@ -118,6 +120,7 @@ fn find_uniform_buffers(
stage,
count: 1,
ty: vk::DescriptorType::UNIFORM_BUFFER,
flags: vk::DescriptorBindingFlags::empty(),
},
);
}
Expand All @@ -142,6 +145,7 @@ fn find_storage_buffers(
stage,
count: 1,
ty: vk::DescriptorType::STORAGE_BUFFER,
flags: vk::DescriptorBindingFlags::empty(),
},
);
}
Expand All @@ -166,6 +170,7 @@ fn find_storage_images(
stage,
count: 1,
ty: vk::DescriptorType::STORAGE_IMAGE,
flags: vk::DescriptorBindingFlags::empty(),
},
);
}
Expand All @@ -190,6 +195,7 @@ fn find_acceleration_structures(
stage,
count: 1,
ty: vk::DescriptorType::ACCELERATION_STRUCTURE_KHR,
flags: vk::DescriptorBindingFlags::empty(),
},
);
}
Expand Down Expand Up @@ -318,6 +324,7 @@ pub(crate) fn build_pipeline_layout(info: &ReflectionInfo) -> PipelineLayoutCrea
stage_flags: binding.stage,
p_immutable_samplers: std::ptr::null(),
});
set.flags.push(binding.flags);
}
Entry::Vacant(entry) => {
entry.insert(DescriptorSetLayoutCreateInfo {
Expand All @@ -328,6 +335,7 @@ pub(crate) fn build_pipeline_layout(info: &ReflectionInfo) -> PipelineLayoutCrea
stage_flags: binding.stage,
p_immutable_samplers: std::ptr::null(),
}],
flags: vec![binding.flags],
persistent: false,
});
}
Expand Down

0 comments on commit a49d400

Please sign in to comment.