Fix descriptor set codegen for SSBO after spirv update (#1275)

This commit is contained in:
nickwilcox 2019-11-18 04:20:07 +11:00 committed by Austin Johnson
parent 0320e75f97
commit b0fb255c02
6 changed files with 19 additions and 17 deletions

View File

@ -3,6 +3,7 @@
- Added Swapchain::surface() - which returns the saved surface - Added Swapchain::surface() - which returns the saved surface
- Added Swapchain::with_old_swapchain() - same as previous Swapchain::new(), if an oldswapchain needs to be used - Added Swapchain::with_old_swapchain() - same as previous Swapchain::new(), if an oldswapchain needs to be used
- Swapchain::new() now doesnt need to have the old_swapchain parameter anymore but requires the ColorSpace - Swapchain::new() now doesnt need to have the old_swapchain parameter anymore but requires the ColorSpace
- Fixed code generated by `shader!` macro so that SSBO's are supported again (broken in 0.16.0).
# Version 0.16.0 (2019-11-01) # Version 0.16.0 (2019-11-01)

View File

@ -39,7 +39,8 @@ fn main() {
// Now initializing the device. // Now initializing the device.
let (device, mut queues) = Device::new(physical, physical.supported_features(), let (device, mut queues) = Device::new(physical, physical.supported_features(),
&DeviceExtensions::none(), [(queue_family, 0.5)].iter().cloned()).unwrap(); &DeviceExtensions{khr_storage_buffer_storage_class:true, ..DeviceExtensions::none()},
[(queue_family, 0.5)].iter().cloned()).unwrap();
// Since we can request multiple queues, the `queues` variable is in fact an iterator. In this // Since we can request multiple queues, the `queues` variable is in fact an iterator. In this
// example we use only one queue, so we just retrieve the first and only element of the // example we use only one queue, so we just retrieve the first and only element of the

View File

@ -77,7 +77,7 @@ fn main() {
q.supports_graphics() && surface.is_supported(q).unwrap_or(false) q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
}).unwrap(); }).unwrap();
let device_ext = DeviceExtensions { khr_swapchain: true, .. DeviceExtensions::none() }; let device_ext = DeviceExtensions { khr_swapchain: true, khr_storage_buffer_storage_class: true, .. DeviceExtensions::none() };
let (device, mut queues) = Device::new(physical, physical.supported_features(), &device_ext, let (device, mut queues) = Device::new(physical, physical.supported_features(), &device_ext,
[(queue_family, 0.5)].iter().cloned()).unwrap(); [(queue_family, 0.5)].iter().cloned()).unwrap();

View File

@ -25,7 +25,8 @@ fn main() {
let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical.queue_families().find(|&q| q.supports_compute()).unwrap(); let queue_family = physical.queue_families().find(|&q| q.supports_compute()).unwrap();
let (device, mut queues) = Device::new(physical, physical.supported_features(), let (device, mut queues) = Device::new(physical, physical.supported_features(),
&DeviceExtensions::none(), [(queue_family, 0.5)].iter().cloned()).unwrap(); &DeviceExtensions { khr_storage_buffer_storage_class: true, ..DeviceExtensions::none() },
[(queue_family, 0.5)].iter().cloned()).unwrap();
let queue = queues.next().unwrap(); let queue = queues.next().unwrap();
mod cs { mod cs {

View File

@ -25,7 +25,8 @@ fn main() {
let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let queue_family = physical.queue_families().find(|&q| q.supports_compute()).unwrap(); let queue_family = physical.queue_families().find(|&q| q.supports_compute()).unwrap();
let (device, mut queues) = Device::new(physical, physical.supported_features(), let (device, mut queues) = Device::new(physical, physical.supported_features(),
&DeviceExtensions::none(), [(queue_family, 0.5)].iter().cloned()).unwrap(); &DeviceExtensions { khr_storage_buffer_storage_class: true, ..DeviceExtensions::none() },
[(queue_family, 0.5)].iter().cloned()).unwrap();
let queue = queues.next().unwrap(); let queue = queues.next().unwrap();
mod cs { mod cs {

View File

@ -34,7 +34,7 @@ pub fn write_descriptor_sets(doc: &Spirv) -> TokenStream {
let set = set_decoration.params[0]; let set = set_decoration.params[0];
// Find which type is pointed to by this variable. // Find which type is pointed to by this variable.
let pointed_ty = pointer_variable_ty(doc, variable_id); let (pointed_ty, storage_class) = pointer_variable_ty(doc, variable_id);
// Name of the variable. // Name of the variable.
let name = spirv_search::name_from_id(doc, variable_id); let name = spirv_search::name_from_id(doc, variable_id);
@ -43,7 +43,7 @@ pub fn write_descriptor_sets(doc: &Spirv) -> TokenStream {
let binding = doc.get_decoration_params(variable_id, Decoration::DecorationBinding).unwrap()[0]; let binding = doc.get_decoration_params(variable_id, Decoration::DecorationBinding).unwrap()[0];
// Find information about the kind of binding for this descriptor. // Find information about the kind of binding for this descriptor.
let (desc_ty, readonly, array_count) = descriptor_infos(doc, pointed_ty, false) let (desc_ty, readonly, array_count) = descriptor_infos(doc, pointed_ty, storage_class, false)
.expect(&format!( .expect(&format!(
"Couldn't find relevant type for uniform `{}` (type {}, maybe unimplemented)", "Couldn't find relevant type for uniform `{}` (type {}, maybe unimplemented)",
name, name,
@ -151,8 +151,8 @@ pub fn write_descriptor_sets(doc: &Spirv) -> TokenStream {
} }
/// Assumes that `variable` is a variable with a `TypePointer` and returns the id of the pointed /// Assumes that `variable` is a variable with a `TypePointer` and returns the id of the pointed
/// type. /// type and the storage class.
fn pointer_variable_ty(doc: &Spirv, variable: u32) -> u32 { fn pointer_variable_ty(doc: &Spirv, variable: u32) -> (u32, StorageClass) {
let var_ty = doc.instructions let var_ty = doc.instructions
.iter() .iter()
.filter_map(|i| match i { .filter_map(|i| match i {
@ -166,8 +166,8 @@ fn pointer_variable_ty(doc: &Spirv, variable: u32) -> u32 {
doc.instructions doc.instructions
.iter() .iter()
.filter_map(|i| match i { .filter_map(|i| match i {
&Instruction::TypePointer { result_id, type_id, .. } &Instruction::TypePointer { result_id, type_id, ref storage_class, .. }
if result_id == var_ty => Some(type_id), if result_id == var_ty => Some((type_id, storage_class.clone())),
_ => None, _ => None,
}) })
.next() .next()
@ -178,17 +178,15 @@ fn pointer_variable_ty(doc: &Spirv, variable: u32) -> u32 {
/// read-only, and the number of array elements. /// read-only, and the number of array elements.
/// ///
/// See also section 14.5.2 of the Vulkan specs: Descriptor Set Interface /// See also section 14.5.2 of the Vulkan specs: Descriptor Set Interface
fn descriptor_infos(doc: &Spirv, pointed_ty: u32, force_combined_image_sampled: bool) fn descriptor_infos(doc: &Spirv, pointed_ty: u32, pointer_storage: StorageClass, force_combined_image_sampled: bool)
-> Option<(TokenStream, bool, u64)> -> Option<(TokenStream, bool, u64)>
{ {
doc.instructions.iter().filter_map(|i| { doc.instructions.iter().filter_map(|i| {
match i { match i {
&Instruction::TypeStruct { result_id, .. } if result_id == pointed_ty => { &Instruction::TypeStruct { result_id, .. } if result_id == pointed_ty => {
// Determine whether there's a Block or BufferBlock decoration.
let decoration_buffer_block = doc.get_decoration_params(pointed_ty, Decoration::DecorationBufferBlock).is_some();
let decoration_block = doc.get_decoration_params(pointed_ty, Decoration::DecorationBlock).is_some(); let decoration_block = doc.get_decoration_params(pointed_ty, Decoration::DecorationBlock).is_some();
assert!(decoration_buffer_block ^ decoration_block, "Found a buffer uniform with neither the Block nor BufferBlock decorations, or both."); assert!(decoration_block, "Structs in shader interface are expected to be decorated with Block");
let is_ssbo = decoration_buffer_block && !decoration_block; let is_ssbo = pointer_storage == StorageClass::StorageClassStorageBuffer;
// Determine whether there's a NonWritable decoration. // Determine whether there's a NonWritable decoration.
//let non_writable = false; // TODO: tricky because the decoration is on struct members //let non_writable = false; // TODO: tricky because the decoration is on struct members
@ -275,14 +273,14 @@ fn descriptor_infos(doc: &Spirv, pointed_ty: u32, force_combined_image_sampled:
} }
&Instruction::TypeSampledImage { result_id, image_type_id } if result_id == pointed_ty &Instruction::TypeSampledImage { result_id, image_type_id } if result_id == pointed_ty
=> descriptor_infos(doc, image_type_id, true), => descriptor_infos(doc, image_type_id, pointer_storage.clone(), true),
&Instruction::TypeSampler { result_id } if result_id == pointed_ty => { &Instruction::TypeSampler { result_id } if result_id == pointed_ty => {
let desc = quote!{ DescriptorDescTy::Sampler }; let desc = quote!{ DescriptorDescTy::Sampler };
Some((desc, true, 1)) Some((desc, true, 1))
} }
&Instruction::TypeArray { result_id, type_id, length_id } if result_id == pointed_ty => { &Instruction::TypeArray { result_id, type_id, length_id } if result_id == pointed_ty => {
let (desc, readonly, arr) = match descriptor_infos(doc, type_id, false) { let (desc, readonly, arr) = match descriptor_infos(doc, type_id, pointer_storage.clone(), false) {
None => return None, None => return None,
Some(v) => v, Some(v) => v,
}; };