diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..5d38d1ce --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,18 @@ +fn_args_density = "Compressed" +fn_args_layout = "Visual" +fn_brace_style = "SameLineWhere" +fn_call_style = "Visual" +fn_empty_single_line = false +format_strings = true +generics_indent = "Visual" +impl_empty_single_line = false +match_block_trailing_comma = true +reorder_imported_names = true +reorder_imports = true +reorder_imports_in_group = true +spaces_around_ranges = true +use_try_shorthand = true +where_density = "Tall" +where_style = "Legacy" +wrap_match_arms = false +write_mode = "Overwrite" diff --git a/glsl-to-spirv/build/build.rs b/glsl-to-spirv/build/build.rs index f576bcf2..25236120 100644 --- a/glsl-to-spirv/build/build.rs +++ b/glsl-to-spirv/build/build.rs @@ -18,9 +18,15 @@ fn main() { } else { // Try to initialize submodules. Don't care if it fails, since this code also runs for // the crates.io package. - let _ = Command::new("git").arg("submodule").arg("update").arg("--init").status(); + let _ = Command::new("git") + .arg("submodule") + .arg("update") + .arg("--init") + .status(); cmake::build("glslang"); - Path::new(&env::var("OUT_DIR").unwrap()).join("bin").join("glslangValidator") + Path::new(&env::var("OUT_DIR").unwrap()) + .join("bin") + .join("glslangValidator") }; if let Err(_) = fs::hard_link(&path, &out_file) { diff --git a/glsl-to-spirv/src/lib.rs b/glsl-to-spirv/src/lib.rs index 5f5e9363..09f6794c 100644 --- a/glsl-to-spirv/src/lib.rs +++ b/glsl-to-spirv/src/lib.rs @@ -43,11 +43,16 @@ fn compile_inner<'a, I>(shaders: I) -> Result }; let file_path = temp_dir.path().join(format!("{}{}", num, extension)); - File::create(&file_path).unwrap().write_all(source.as_bytes()).unwrap(); + File::create(&file_path) + .unwrap() + .write_all(source.as_bytes()) + .unwrap(); command.arg(file_path); } - let output = command.output().expect("Failed to execute glslangValidator"); + let output = command + .output() + .expect("Failed to execute glslangValidator"); if output.status.success() { let spirv_output = File::open(output_file).expect("failed to open SPIR-V output file"); diff --git a/vulkano-shaders/src/descriptor_sets.rs b/vulkano-shaders/src/descriptor_sets.rs index 9c4470d8..ef987dd2 100644 --- a/vulkano-shaders/src/descriptor_sets.rs +++ b/vulkano-shaders/src/descriptor_sets.rs @@ -29,10 +29,14 @@ pub fn write_descriptor_sets(doc: &parse::Spirv) -> String { // Looping to find all the elements that have the `DescriptorSet` decoration. for instruction in doc.instructions.iter() { let (variable_id, descriptor_set) = match instruction { - &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationDescriptorSet, ref params } => { + &parse::Instruction::Decorate { + target_id, + decoration: enums::Decoration::DecorationDescriptorSet, + ref params, + } => { (target_id, params[0]) }, - _ => continue + _ => continue, }; // Find which type is pointed to by this variable. @@ -41,36 +45,52 @@ pub fn write_descriptor_sets(doc: &parse::Spirv) -> String { let name = ::name_from_id(doc, variable_id); // Find the binding point of this descriptor. - let binding = doc.instructions.iter().filter_map(|i| { - match i { - &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationBinding, ref params } if target_id == variable_id => { - Some(params[0]) - }, - _ => None, // TODO: other types - } - }).next().expect(&format!("Uniform `{}` is missing a binding", name)); + let binding = doc.instructions + .iter() + .filter_map(|i| { + match i { + &parse::Instruction::Decorate { + target_id, + decoration: enums::Decoration::DecorationBinding, + ref params, + } if target_id == variable_id => { + Some(params[0]) + }, + _ => None, // TODO: other types + } + }) + .next() + .expect(&format!("Uniform `{}` is missing a binding", name)); // Find informations about the kind of binding for this descriptor. - let (desc_ty, readonly, array_count) = descriptor_infos(doc, pointed_ty, false).expect(&format!("Couldn't find relevant type for uniform `{}` (type {}, maybe unimplemented)", name, pointed_ty)); + let (desc_ty, readonly, array_count) = descriptor_infos(doc, pointed_ty, false) + .expect(&format!("Couldn't find relevant type for uniform `{}` (type {}, maybe \ + unimplemented)", + name, + pointed_ty)); descriptors.push(Descriptor { - name: name, - desc_ty: desc_ty, - set: descriptor_set, - binding: binding, - array_count: array_count, - readonly: readonly, - }); + name: name, + desc_ty: desc_ty, + set: descriptor_set, + binding: binding, + array_count: array_count, + readonly: readonly, + }); } // Looping to find all the push constant structs. let mut push_constants_size = 0; for instruction in doc.instructions.iter() { let type_id = match instruction { - &parse::Instruction::TypePointer { type_id, storage_class: enums::StorageClass::StorageClassPushConstant, .. } => { + &parse::Instruction::TypePointer { + type_id, + storage_class: enums::StorageClass::StorageClassPushConstant, + .. + } => { type_id }, - _ => continue + _ => continue, }; let (_, size, _) = ::structs::type_from_id(doc, type_id); @@ -79,54 +99,76 @@ pub fn write_descriptor_sets(doc: &parse::Spirv) -> String { } // Writing the body of the `descriptor` method. - let descriptor_body = descriptors.iter().map(|d| { - format!("({set}, {binding}) => Some(DescriptorDesc {{ + let descriptor_body = descriptors + .iter() + .map(|d| { + format!( + "({set}, {binding}) => Some(DescriptorDesc {{ ty: {desc_ty}, array_count: {array_count}, stages: self.0.clone(), readonly: {readonly}, - }}),", set = d.set, binding = d.binding, desc_ty = d.desc_ty, array_count = d.array_count, - readonly = if d.readonly { "true" } else { "false" }) + }}),", + set = d.set, + binding = d.binding, + desc_ty = d.desc_ty, + array_count = d.array_count, + readonly = if d.readonly { "true" } else { "false" } + ) - }).collect::>().concat(); + }) + .collect::>() + .concat(); let num_sets = 1 + descriptors.iter().fold(0, |s, d| cmp::max(s, d.set)); // Writing the body of the `num_bindings_in_set` method. let num_bindings_in_set_body = { - (0 .. num_sets).map(|set| { - let num = 1 + descriptors.iter().filter(|d| d.set == set) - .fold(0, |s, d| cmp::max(s, d.binding)); - format!("{set} => Some({num}),", set = set, num = num) - }).collect::>().concat() + (0 .. num_sets) + .map(|set| { + let num = 1 + + descriptors + .iter() + .filter(|d| d.set == set) + .fold(0, |s, d| cmp::max(s, d.binding)); + format!("{set} => Some({num}),", set = set, num = num) + }) + .collect::>() + .concat() }; // Writing the body of the `descriptor_by_name_body` method. - let descriptor_by_name_body = descriptors.iter().map(|d| { - format!(r#"{name:?} => Some(({set}, {binding})),"#, - name = d.name, set = d.set, binding = d.binding) - }).collect::>().concat(); + let descriptor_by_name_body = descriptors + .iter() + .map(|d| { + format!(r#"{name:?} => Some(({set}, {binding})),"#, + name = d.name, + set = d.set, + binding = d.binding) + }) + .collect::>() + .concat(); // Writing the body of the `num_push_constants_ranges` method. let num_push_constants_ranges_body = { - if push_constants_size == 0 { - "0" - } else { - "1" - } + if push_constants_size == 0 { "0" } else { "1" } }; // Writing the body of the `push_constants_range` method. - let push_constants_range_body = format!(r#" + let push_constants_range_body = format!( + r#" if num != 0 || {pc_size} == 0 {{ return None; }} Some(PipelineLayoutDescPcRange {{ offset: 0, // FIXME: not necessarily true size: {pc_size}, stages: ShaderStages::all(), // FIXME: wrong }}) - "#, pc_size = push_constants_size); + "#, + pc_size = push_constants_size + ); - format!(r#" + format!( + r#" #[derive(Debug, Clone)] pub struct Layout(ShaderStages); @@ -168,32 +210,45 @@ pub fn write_descriptor_sets(doc: &parse::Spirv) -> String { }} }} }} - "#, num_sets = num_sets, num_bindings_in_set_body = num_bindings_in_set_body, - descriptor_by_name_body = descriptor_by_name_body, descriptor_body = descriptor_body, - num_push_constants_ranges_body = num_push_constants_ranges_body, - push_constants_range_body = push_constants_range_body) + "#, + num_sets = num_sets, + num_bindings_in_set_body = num_bindings_in_set_body, + descriptor_by_name_body = descriptor_by_name_body, + descriptor_body = descriptor_body, + num_push_constants_ranges_body = num_push_constants_ranges_body, + push_constants_range_body = push_constants_range_body + ) } /// Assumes that `variable` is a variable with a `TypePointer` and returns the id of the pointed /// type. fn pointer_variable_ty(doc: &parse::Spirv, variable: u32) -> u32 { - let var_ty = doc.instructions.iter().filter_map(|i| { - match i { - &parse::Instruction::Variable { result_type_id, result_id, .. } if result_id == variable => { - Some(result_type_id) - }, - _ => None - } - }).next().unwrap(); + let var_ty = doc.instructions + .iter() + .filter_map(|i| match i { + &parse::Instruction::Variable { + result_type_id, + result_id, + .. + } if result_id == variable => { + Some(result_type_id) + }, + _ => None, + }) + .next() + .unwrap(); - doc.instructions.iter().filter_map(|i| { - match i { - &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == var_ty => { - Some(type_id) - }, - _ => None - } - }).next().unwrap() + doc.instructions + .iter() + .filter_map(|i| match i { + &parse::Instruction::TypePointer { result_id, type_id, .. } + if result_id == var_ty => { + Some(type_id) + }, + _ => None, + }) + .next() + .unwrap() } /// Returns a `DescriptorDescTy` constructor, a bool indicating whether the descriptor is @@ -201,8 +256,7 @@ fn pointer_variable_ty(doc: &parse::Spirv, variable: u32) -> u32 { /// /// See also section 14.5.2 of the Vulkan specs: Descriptor Set Interface fn descriptor_infos(doc: &parse::Spirv, pointed_ty: u32, force_combined_image_sampled: bool) - -> Option<(String, bool, u64)> -{ + -> Option<(String, bool, u64)> { doc.instructions.iter().filter_map(|i| { match i { &parse::Instruction::TypeStruct { result_id, .. } if result_id == pointed_ty => { diff --git a/vulkano-shaders/src/entry_point.rs b/vulkano-shaders/src/entry_point.rs index 935b19b5..1f8d0694 100644 --- a/vulkano-shaders/src/entry_point.rs +++ b/vulkano-shaders/src/entry_point.rs @@ -10,74 +10,117 @@ use enums; use parse; -use is_builtin; -use name_from_id; -use location_decoration; use format_from_id; +use is_builtin; +use location_decoration; +use name_from_id; pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) { let (execution, ep_name, interface) = match instruction { - &parse::Instruction::EntryPoint { ref execution, ref name, ref interface, .. } => { + &parse::Instruction::EntryPoint { + ref execution, + ref name, + ref interface, + .. + } => { (execution, name, interface) }, - _ => unreachable!() + _ => unreachable!(), }; - let capitalized_ep_name: String = ep_name.chars().take(1).flat_map(|c| c.to_uppercase()) - .chain(ep_name.chars().skip(1)).collect(); + let capitalized_ep_name: String = ep_name + .chars() + .take(1) + .flat_map(|c| c.to_uppercase()) + .chain(ep_name.chars().skip(1)) + .collect(); - let interface_structs = write_interface_structs(doc, &capitalized_ep_name, interface, - match *execution { - enums::ExecutionModel::ExecutionModelTessellationControl => true, - enums::ExecutionModel::ExecutionModelTessellationEvaluation => true, - enums::ExecutionModel::ExecutionModelGeometry => true, - _ => false - }, - match *execution { - enums::ExecutionModel::ExecutionModelTessellationControl => true, - _ => false, - }); + let interface_structs = + write_interface_structs(doc, + &capitalized_ep_name, + interface, + match *execution { + enums::ExecutionModel::ExecutionModelTessellationControl => + true, + enums::ExecutionModel::ExecutionModelTessellationEvaluation => + true, + enums::ExecutionModel::ExecutionModelGeometry => true, + _ => false, + }, + match *execution { + enums::ExecutionModel::ExecutionModelTessellationControl => + true, + _ => false, + }); let (ty, f_call) = match *execution { enums::ExecutionModel::ExecutionModelVertex => { - let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name); - let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ vertex: true, .. ShaderStages::none() }}))", capitalized_ep_name); + let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), {0}Input, \ + {0}Output, Layout>", + capitalized_ep_name); + let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() \ + as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ vertex: \ + true, .. ShaderStages::none() }}))", + capitalized_ep_name); (t, f) }, enums::ExecutionModel::ExecutionModelTessellationControl => { - let t = format!("::vulkano::pipeline::shader::TessControlShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name); - let f = format!("tess_control_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_control: true, .. ShaderStages::none() }}))", capitalized_ep_name); + let t = format!("::vulkano::pipeline::shader::TessControlShaderEntryPoint<(), \ + {0}Input, {0}Output, Layout>", + capitalized_ep_name); + let f = format!("tess_control_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.\ + as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ \ + tessellation_control: true, .. ShaderStages::none() }}))", + capitalized_ep_name); (t, f) }, enums::ExecutionModel::ExecutionModelTessellationEvaluation => { - let t = format!("::vulkano::pipeline::shader::TessEvaluationShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name); - let f = format!("tess_evaluation_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ tessellation_evaluation: true, .. ShaderStages::none() }}))", capitalized_ep_name); + let t = format!("::vulkano::pipeline::shader::TessEvaluationShaderEntryPoint<(), \ + {0}Input, {0}Output, Layout>", + capitalized_ep_name); + let f = format!("tess_evaluation_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.\ + as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ \ + tessellation_evaluation: true, .. ShaderStages::none() }}))", + capitalized_ep_name); (t, f) }, enums::ExecutionModel::ExecutionModelGeometry => { - let t = format!("::vulkano::pipeline::shader::GeometryShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name); - let f = format!("geometry_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ geometry: true, .. ShaderStages::none() }}))", capitalized_ep_name); + let t = format!("::vulkano::pipeline::shader::GeometryShaderEntryPoint<(), {0}Input, \ + {0}Output, Layout>", + capitalized_ep_name); + let f = format!("geometry_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.\ + as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ \ + geometry: true, .. ShaderStages::none() }}))", + capitalized_ep_name); (t, f) }, enums::ExecutionModel::ExecutionModelFragment => { - let t = format!("::vulkano::pipeline::shader::FragmentShaderEntryPoint<(), {0}Input, {0}Output, Layout>", capitalized_ep_name); - let f = format!("fragment_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ fragment: true, .. ShaderStages::none() }}))", capitalized_ep_name); + let t = format!("::vulkano::pipeline::shader::FragmentShaderEntryPoint<(), {0}Input, \ + {0}Output, Layout>", + capitalized_ep_name); + let f = format!("fragment_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.\ + as_ptr() as *const _), {0}Input, {0}Output, Layout(ShaderStages {{ \ + fragment: true, .. ShaderStages::none() }}))", + capitalized_ep_name); (t, f) }, enums::ExecutionModel::ExecutionModelGLCompute => { (format!("::vulkano::pipeline::shader::ComputeShaderEntryPoint<(), Layout>"), - format!("compute_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() }}))")) + format!("compute_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as \ + *const _), Layout(ShaderStages {{ compute: true, .. ShaderStages::none() \ + }}))")) }, enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"), }; - let entry_point = format!(r#" + let entry_point = format!( + r#" /// Returns a logical struct describing the entry point named `{ep_name}`. #[inline] #[allow(unsafe_code)] @@ -88,18 +131,24 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) - self.shader.{f_call} }} }} - "#, ep_name = ep_name, ep_name_lenp1 = ep_name.chars().count() + 1, ty = ty, - encoded_ep_name = ep_name.chars().map(|c| (c as u32).to_string()) - .collect::>().join(", "), - f_call = f_call); + "#, + ep_name = ep_name, + ep_name_lenp1 = ep_name.chars().count() + 1, + ty = ty, + encoded_ep_name = ep_name + .chars() + .map(|c| (c as u32).to_string()) + .collect::>() + .join(", "), + f_call = f_call + ); (interface_structs, entry_point) } fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32], ignore_first_array_in: bool, ignore_first_array_out: bool) - -> String -{ + -> String { let mut input_elements = Vec::new(); let mut output_elements = Vec::new(); @@ -107,30 +156,40 @@ fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interf for interface in interface.iter() { for i in doc.instructions.iter() { match i { - &parse::Instruction::Variable { result_type_id, result_id, ref storage_class, .. } - if &result_id == interface => - { + &parse::Instruction::Variable { + result_type_id, + result_id, + ref storage_class, + .. + } if &result_id == interface => { if is_builtin(doc, result_id) { continue; } let (to_write, ignore_first_array) = match storage_class { - &enums::StorageClass::StorageClassInput => (&mut input_elements, ignore_first_array_in), - &enums::StorageClass::StorageClassOutput => (&mut output_elements, ignore_first_array_out), - _ => continue + &enums::StorageClass::StorageClassInput => (&mut input_elements, + ignore_first_array_in), + &enums::StorageClass::StorageClassOutput => (&mut output_elements, + ignore_first_array_out), + _ => continue, }; let name = name_from_id(doc, result_id); - if name == "__unnamed" { continue; } // FIXME: hack + if name == "__unnamed" { + continue; + } // FIXME: hack let loc = match location_decoration(doc, result_id) { Some(l) => l, - None => panic!("Attribute `{}` (id {}) is missing a location", name, result_id) + None => panic!("Attribute `{}` (id {}) is missing a location", + name, + result_id), }; - to_write.push((loc, name, format_from_id(doc, result_type_id, ignore_first_array))); + to_write + .push((loc, name, format_from_id(doc, result_type_id, ignore_first_array))); }, - _ => () + _ => (), } } } @@ -139,24 +198,34 @@ fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interf &write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements) } -fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))]) -> String { +fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))]) + -> String { // Checking for overlapping elements. for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() { for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) { if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) || - (loc2 < loc && loc2 + loc_len2 as u32 > loc) + (loc2 < loc && loc2 + loc_len2 as u32 > loc) { panic!("The locations of attributes `{}` (start={}, size={}) \ and `{}` (start={}, size={}) overlap", - name, loc, loc_len, name2, loc2, loc_len2); + name, + loc, + loc_len, + name2, + loc2, + loc_len2); } } } - let body = attributes.iter().enumerate().map(|(num, &(loc, ref name, (ref ty, num_locs)))| { - assert!(num_locs >= 1); + let body = attributes + .iter() + .enumerate() + .map(|(num, &(loc, ref name, (ref ty, num_locs)))| { + assert!(num_locs >= 1); - format!("if self.num == {} {{ + format!( + "if self.num == {} {{ self.num += 1; return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{ @@ -164,39 +233,61 @@ fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String format: ::vulkano::format::Format::{}, name: Some(::std::borrow::Cow::Borrowed(\"{}\")) }}); - }}", num, loc, loc as usize + num_locs, ty, name) - }).collect::>().join(""); + }}", + num, + loc, + loc as usize + num_locs, + ty, + name + ) + }) + .collect::>() + .join(""); - format!(" + format!( + " #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct {name}; - #[allow(unsafe_code)] - unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for {name} {{ + \ + #[allow(unsafe_code)] + unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for \ + {name} {{ type Iter = {name}Iter; fn elements(&self) -> {name}Iter {{ - {name}Iter {{ num: 0 }} + \ + {name}Iter {{ num: 0 }} }} }} #[derive(Debug, Copy, Clone)] - pub struct {name}Iter {{ num: u16 }} + \ + pub struct {name}Iter {{ num: u16 }} impl Iterator for {name}Iter {{ - type Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry; + type \ + Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry; #[inline] - fn next(&mut self) -> Option {{ + \ + fn next(&mut self) -> Option {{ {body} None - }} + \ + }} #[inline] fn size_hint(&self) -> (usize, Option) {{ - let len = ({len} - self.num) as usize; + \ + let len = ({len} - self.num) as usize; (len, Some(len)) }} - }} + \ + }} impl ExactSizeIterator for {name}Iter {{}} - ", name = struct_name, body = body, len = attributes.len()) + ", + name = struct_name, + body = body, + len = attributes.len() + ) } diff --git a/vulkano-shaders/src/lib.rs b/vulkano-shaders/src/lib.rs index b52aff1f..89ba622a 100644 --- a/vulkano-shaders/src/lib.rs +++ b/vulkano-shaders/src/lib.rs @@ -17,8 +17,8 @@ use std::io::Read; use std::io::Write; use std::path::Path; -pub use parse::ParseError; pub use glsl_to_spirv::ShaderType; +pub use parse::ParseError; mod descriptor_sets; mod entry_point; @@ -43,14 +43,16 @@ pub fn build_glsl_shaders<'a, I>(shaders: I) let shader_content = { let mut s = String::new(); - File::open(shader).expect("failed to open shader").read_to_string(&mut s) - .expect("failed to read shader content"); + File::open(shader) + .expect("failed to open shader") + .read_to_string(&mut s) + .expect("failed to read shader content"); s }; fs::create_dir_all(&dest.join("shaders").join(shader.parent().unwrap())).unwrap(); let mut file_output = File::create(&dest.join("shaders").join(shader)) - .expect("failed to open shader output"); + .expect("failed to open shader output"); let content = match glsl_to_spirv::compile(&shader_content, ty) { Ok(compiled) => compiled, @@ -65,13 +67,14 @@ pub fn reflect(name: &str, mut spirv: R) -> Result where R: Read { let mut data = Vec::new(); - try!(spirv.read_to_end(&mut data)); + spirv.read_to_end(&mut data)?; // now parsing the document - let doc = try!(parse::parse_spirv(&data)); + let doc = parse::parse_spirv(&data)?; let mut output = String::new(); - output.push_str(r#" + output.push_str( + r#" #[allow(unused_imports)] use std::sync::Arc; #[allow(unused_imports)] @@ -109,16 +112,19 @@ pub fn reflect(name: &str, mut spirv: R) -> Result use vulkano::descriptor::pipeline_layout::PipelineLayoutDescNames; #[allow(unused_imports)] use vulkano::descriptor::pipeline_layout::PipelineLayoutDescPcRange; - "#); + "#, + ); { // contains the data that was passed as input to this function - let spirv_data = data.iter().map(|&byte| byte.to_string()) - .collect::>() - .join(", "); + let spirv_data = data.iter() + .map(|&byte| byte.to_string()) + .collect::>() + .join(", "); // writing the header - output.push_str(&format!(r#" + output.push_str(&format!( + r#" pub struct {name} {{ shader: ::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule>, }} @@ -131,23 +137,29 @@ impl {name} {{ -> Result<{name}, ::vulkano::OomError> {{ - "#, name = name)); + "#, + name = name + )); // checking whether each required capability is enabled in the vulkan device for i in doc.instructions.iter() { if let &parse::Instruction::Capability(ref cap) = i { if let Some(cap) = capability_name(cap) { - output.push_str(&format!(r#" + output.push_str(&format!( + r#" if !device.enabled_features().{cap} {{ panic!("capability {{:?}} not enabled", "{cap}") // FIXME: error //return Err(CapabilityNotEnabled); - }}"#, cap = cap)); + }}"#, + cap = cap + )); } } } // follow-up of the header - output.push_str(&format!(r#" + output.push_str(&format!( + r#" unsafe {{ let data = [{spirv_data}]; @@ -163,7 +175,10 @@ impl {name} {{ pub fn module(&self) -> &::std::sync::Arc<::vulkano::pipeline::shader::ShaderModule> {{ &self.shader }} - "#, name = name, spirv_data = spirv_data)); + "#, + name = name, + spirv_data = spirv_data + )); // writing one method for each entry point of this module let mut outside_impl = String::new(); @@ -176,9 +191,11 @@ impl {name} {{ } // footer - output.push_str(&format!(r#" + output.push_str(&format!( + r#" }} - "#)); + "# + )); output.push_str(&outside_impl); @@ -222,7 +239,11 @@ impl From for Error { fn format_from_id(doc: &parse::Spirv, searched: u32, ignore_first_array: bool) -> (String, usize) { for instruction in doc.instructions.iter() { match instruction { - &parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => { + &parse::Instruction::TypeInt { + result_id, + width, + signedness, + } if result_id == searched => { assert!(!ignore_first_array); return (match (width, signedness) { (8, true) => "R8Sint", @@ -233,18 +254,24 @@ fn format_from_id(doc: &parse::Spirv, searched: u32, ignore_first_array: bool) - (32, false) => "R32Uint", (64, true) => "R64Sint", (64, false) => "R64Uint", - _ => panic!() - }.to_owned(), 1); + _ => panic!(), + }.to_owned(), + 1); }, &parse::Instruction::TypeFloat { result_id, width } if result_id == searched => { assert!(!ignore_first_array); return (match width { 32 => "R32Sfloat", 64 => "R64Sfloat", - _ => panic!() - }.to_owned(), 1); + _ => panic!(), + }.to_owned(), + 1); }, - &parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => { + &parse::Instruction::TypeVector { + result_id, + component_id, + count, + } if result_id == searched => { assert!(!ignore_first_array); let (format, sz) = format_from_id(doc, component_id, false); assert!(format.starts_with("R32")); @@ -252,37 +279,55 @@ fn format_from_id(doc: &parse::Spirv, searched: u32, ignore_first_array: bool) - let format = if count == 1 { format } else if count == 2 { - format!("R32G32{}", &format[3..]) + format!("R32G32{}", &format[3 ..]) } else if count == 3 { - format!("R32G32B32{}", &format[3..]) + format!("R32G32B32{}", &format[3 ..]) } else if count == 4 { - format!("R32G32B32A32{}", &format[3..]) + format!("R32G32B32A32{}", &format[3 ..]) } else { panic!("Found vector type with more than 4 elements") }; return (format, sz); }, - &parse::Instruction::TypeMatrix { result_id, column_type_id, column_count } if result_id == searched => { + &parse::Instruction::TypeMatrix { + result_id, + column_type_id, + column_count, + } if result_id == searched => { assert!(!ignore_first_array); let (format, sz) = format_from_id(doc, column_type_id, false); return (format, sz * column_count as usize); }, - &parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => { + &parse::Instruction::TypeArray { + result_id, + type_id, + length_id, + } if result_id == searched => { if ignore_first_array { return format_from_id(doc, type_id, false); } let (format, sz) = format_from_id(doc, type_id, false); - let len = doc.instructions.iter().filter_map(|e| { - match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None } - }).next().expect("failed to find array length"); + let len = doc.instructions + .iter() + .filter_map(|e| match e { + &parse::Instruction::Constant { + result_id, + ref data, + .. + } if result_id == length_id => Some(data.clone()), + _ => None, + }) + .next() + .expect("failed to find array length"); let len = len.iter().rev().fold(0u64, |a, &b| (a << 32) | b as u64); return (format, sz * len as usize); }, - &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == searched => { + &parse::Instruction::TypePointer { result_id, type_id, .. } + if result_id == searched => { return format_from_id(doc, type_id, ignore_first_array); }, - _ => () + _ => (), } } @@ -290,8 +335,13 @@ fn format_from_id(doc: &parse::Spirv, searched: u32, ignore_first_array: bool) - } fn name_from_id(doc: &parse::Spirv, searched: u32) -> String { - doc.instructions.iter().filter_map(|i| { - if let &parse::Instruction::Name { target_id, ref name } = i { + doc.instructions + .iter() + .filter_map(|i| if let &parse::Instruction::Name { + target_id, + ref name, + } = i + { if target_id == searched { Some(name.clone()) } else { @@ -299,14 +349,21 @@ fn name_from_id(doc: &parse::Spirv, searched: u32) -> String { } } else { None - } - }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None }) - .unwrap_or("__unnamed".to_owned()) + }) + .next() + .and_then(|n| if !n.is_empty() { Some(n) } else { None }) + .unwrap_or("__unnamed".to_owned()) } fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) -> String { - doc.instructions.iter().filter_map(|i| { - if let &parse::Instruction::MemberName { target_id, member, ref name } = i { + doc.instructions + .iter() + .filter_map(|i| if let &parse::Instruction::MemberName { + target_id, + member, + ref name, + } = i + { if target_id == searched && member == searched_member { Some(name.clone()) } else { @@ -314,14 +371,21 @@ fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) } } else { None - } - }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None }) - .unwrap_or("__unnamed".to_owned()) + }) + .next() + .and_then(|n| if !n.is_empty() { Some(n) } else { None }) + .unwrap_or("__unnamed".to_owned()) } fn location_decoration(doc: &parse::Spirv, searched: u32) -> Option { - doc.instructions.iter().filter_map(|i| { - if let &parse::Instruction::Decorate { target_id, decoration: enums::Decoration::DecorationLocation, ref params } = i { + doc.instructions + .iter() + .filter_map(|i| if let &parse::Instruction::Decorate { + target_id, + decoration: enums::Decoration::DecorationLocation, + ref params, + } = i + { if target_id == searched { Some(params[0]) } else { @@ -329,33 +393,39 @@ fn location_decoration(doc: &parse::Spirv, searched: u32) -> Option { } } else { None - } - }).next() + }) + .next() } /// Returns true if a `BuiltIn` decorator is applied on an id. fn is_builtin(doc: &parse::Spirv, id: u32) -> bool { for instruction in &doc.instructions { match *instruction { - parse::Instruction::Decorate { target_id, - decoration: enums::Decoration::DecorationBuiltIn, - .. } if target_id == id => - { + parse::Instruction::Decorate { + target_id, + decoration: enums::Decoration::DecorationBuiltIn, + .. + } if target_id == id => { return true; }, - parse::Instruction::MemberDecorate { target_id, - decoration: enums::Decoration::DecorationBuiltIn, - .. } if target_id == id => - { + parse::Instruction::MemberDecorate { + target_id, + decoration: enums::Decoration::DecorationBuiltIn, + .. + } if target_id == id => { return true; }, - _ => () + _ => (), } } for instruction in &doc.instructions { match *instruction { - parse::Instruction::Variable { result_type_id, result_id, .. } if result_id == id => { + parse::Instruction::Variable { + result_type_id, + result_id, + .. + } if result_id == id => { return is_builtin(doc, result_type_id); }, parse::Instruction::TypeArray { result_id, type_id, .. } if result_id == id => { @@ -364,15 +434,20 @@ fn is_builtin(doc: &parse::Spirv, id: u32) -> bool { parse::Instruction::TypeRuntimeArray { result_id, type_id } if result_id == id => { return is_builtin(doc, type_id); }, - parse::Instruction::TypeStruct { result_id, ref member_types } if result_id == id => { + parse::Instruction::TypeStruct { + result_id, + ref member_types, + } if result_id == id => { for &mem in member_types { - if is_builtin(doc, mem) { return true; } + if is_builtin(doc, mem) { + return true; + } } }, parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == id => { return is_builtin(doc, type_id); }, - _ => () + _ => (), } } @@ -407,14 +482,21 @@ fn capability_name(cap: &enums::Capability) -> Option<&'static str> { enums::Capability::CapabilityLiteralSampler => panic!(), // not supported enums::Capability::CapabilityAtomicStorage => panic!(), // not supported enums::Capability::CapabilityInt16 => Some("shader_int16"), - enums::Capability::CapabilityTessellationPointSize => Some("shader_tessellation_and_geometry_point_size"), - enums::Capability::CapabilityGeometryPointSize => Some("shader_tessellation_and_geometry_point_size"), + enums::Capability::CapabilityTessellationPointSize => + Some("shader_tessellation_and_geometry_point_size"), + enums::Capability::CapabilityGeometryPointSize => + Some("shader_tessellation_and_geometry_point_size"), enums::Capability::CapabilityImageGatherExtended => Some("shader_image_gather_extended"), - enums::Capability::CapabilityStorageImageMultisample => Some("shader_storage_image_multisample"), - enums::Capability::CapabilityUniformBufferArrayDynamicIndexing => Some("shader_uniform_buffer_array_dynamic_indexing"), - enums::Capability::CapabilitySampledImageArrayDynamicIndexing => Some("shader_sampled_image_array_dynamic_indexing"), - enums::Capability::CapabilityStorageBufferArrayDynamicIndexing => Some("shader_storage_buffer_array_dynamic_indexing"), - enums::Capability::CapabilityStorageImageArrayDynamicIndexing => Some("shader_storage_image_array_dynamic_indexing"), + enums::Capability::CapabilityStorageImageMultisample => + Some("shader_storage_image_multisample"), + enums::Capability::CapabilityUniformBufferArrayDynamicIndexing => + Some("shader_uniform_buffer_array_dynamic_indexing"), + enums::Capability::CapabilitySampledImageArrayDynamicIndexing => + Some("shader_sampled_image_array_dynamic_indexing"), + enums::Capability::CapabilityStorageBufferArrayDynamicIndexing => + Some("shader_storage_buffer_array_dynamic_indexing"), + enums::Capability::CapabilityStorageImageArrayDynamicIndexing => + Some("shader_storage_image_array_dynamic_indexing"), enums::Capability::CapabilityClipDistance => Some("shader_clip_distance"), enums::Capability::CapabilityCullDistance => Some("shader_cull_distance"), enums::Capability::CapabilityImageCubeArray => Some("image_cube_array"), @@ -432,14 +514,17 @@ fn capability_name(cap: &enums::Capability) -> Option<&'static str> { enums::Capability::CapabilitySampledBuffer => None, // always supported enums::Capability::CapabilityImageBuffer => None, // always supported enums::Capability::CapabilityImageMSArray => Some("shader_storage_image_multisample"), - enums::Capability::CapabilityStorageImageExtendedFormats => Some("shader_storage_image_extended_formats"), + enums::Capability::CapabilityStorageImageExtendedFormats => + Some("shader_storage_image_extended_formats"), enums::Capability::CapabilityImageQuery => None, // always supported enums::Capability::CapabilityDerivativeControl => None, // always supported enums::Capability::CapabilityInterpolationFunction => Some("sample_rate_shading"), enums::Capability::CapabilityTransformFeedback => panic!(), // not supported enums::Capability::CapabilityGeometryStreams => panic!(), // not supported - enums::Capability::CapabilityStorageImageReadWithoutFormat => Some("shader_storage_image_read_without_format"), - enums::Capability::CapabilityStorageImageWriteWithoutFormat => Some("shader_storage_image_write_without_format"), + enums::Capability::CapabilityStorageImageReadWithoutFormat => + Some("shader_storage_image_read_without_format"), + enums::Capability::CapabilityStorageImageWriteWithoutFormat => + Some("shader_storage_image_write_without_format"), enums::Capability::CapabilityMultiViewport => Some("multi_viewport"), } } diff --git a/vulkano-shaders/src/parse.rs b/vulkano-shaders/src/parse.rs index ac10e655..7f209dff 100644 --- a/vulkano-shaders/src/parse.rs +++ b/vulkano-shaders/src/parse.rs @@ -19,15 +19,21 @@ pub fn parse_spirv(data: &[u8]) -> Result { // on the magic number at the start of the file let data = if data[0] == 0x07 && data[1] == 0x23 && data[2] == 0x02 && data[3] == 0x03 { // big endian - data.chunks(4).map(|c| { - ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | c[3] as u32 - }).collect::>() + data.chunks(4) + .map(|c| { + ((c[0] as u32) << 24) | ((c[1] as u32) << 16) | ((c[2] as u32) << 8) | + c[3] as u32 + }) + .collect::>() } else if data[3] == 0x07 && data[2] == 0x23 && data[1] == 0x02 && data[0] == 0x03 { // little endian - data.chunks(4).map(|c| { - ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | c[0] as u32 - }).collect::>() + data.chunks(4) + .map(|c| { + ((c[3] as u32) << 24) | ((c[2] as u32) << 16) | ((c[1] as u32) << 8) | + c[0] as u32 + }) + .collect::>() } else { return Err(ParseError::MissingHeader); @@ -52,9 +58,9 @@ fn parse_u32s(i: &[u32]) -> Result { let instructions = { let mut ret = Vec::new(); - let mut i = &i[5..]; + let mut i = &i[5 ..]; while i.len() >= 1 { - let (instruction, rest) = try!(parse_instruction(i)); + let (instruction, rest) = parse_instruction(i)?; ret.push(instruction); i = rest; } @@ -62,10 +68,10 @@ fn parse_u32s(i: &[u32]) -> Result { }; Ok(Spirv { - version: version, - bound: i[3], - instructions: instructions, - }) + version: version, + bound: i[3], + instructions: instructions, + }) } /// Error that can happen when parsing. @@ -89,30 +95,90 @@ pub enum Instruction { Unknown(u16, Vec), Nop, Name { target_id: u32, name: String }, - MemberName { target_id: u32, member: u32, name: String }, + MemberName { + target_id: u32, + member: u32, + name: String, + }, ExtInstImport { result_id: u32, name: String }, MemoryModel(AddressingModel, MemoryModel), - EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec }, + EntryPoint { + execution: ExecutionModel, + id: u32, + name: String, + interface: Vec, + }, Capability(Capability), TypeVoid { result_id: u32 }, TypeBool { result_id: u32 }, - TypeInt { result_id: u32, width: u32, signedness: bool }, + TypeInt { + result_id: u32, + width: u32, + signedness: bool, + }, TypeFloat { result_id: u32, width: u32 }, - TypeVector { result_id: u32, component_id: u32, count: u32 }, - TypeMatrix { result_id: u32, column_type_id: u32, column_count: u32 }, - TypeImage { result_id: u32, sampled_type_id: u32, dim: Dim, depth: Option, arrayed: bool, ms: bool, sampled: Option, format: ImageFormat, access: Option }, + TypeVector { + result_id: u32, + component_id: u32, + count: u32, + }, + TypeMatrix { + result_id: u32, + column_type_id: u32, + column_count: u32, + }, + TypeImage { + result_id: u32, + sampled_type_id: u32, + dim: Dim, + depth: Option, + arrayed: bool, + ms: bool, + sampled: Option, + format: ImageFormat, + access: Option, + }, TypeSampler { result_id: u32 }, TypeSampledImage { result_id: u32, image_type_id: u32 }, - TypeArray { result_id: u32, type_id: u32, length_id: u32 }, + TypeArray { + result_id: u32, + type_id: u32, + length_id: u32, + }, TypeRuntimeArray { result_id: u32, type_id: u32 }, - TypeStruct { result_id: u32, member_types: Vec }, + TypeStruct { + result_id: u32, + member_types: Vec, + }, TypeOpaque { result_id: u32, name: String }, - TypePointer { result_id: u32, storage_class: StorageClass, type_id: u32 }, - Constant { result_type_id: u32, result_id: u32, data: Vec }, + TypePointer { + result_id: u32, + storage_class: StorageClass, + type_id: u32, + }, + Constant { + result_type_id: u32, + result_id: u32, + data: Vec, + }, FunctionEnd, - Variable { result_type_id: u32, result_id: u32, storage_class: StorageClass, initializer: Option }, - Decorate { target_id: u32, decoration: Decoration, params: Vec }, - MemberDecorate { target_id: u32, member: u32, decoration: Decoration, params: Vec }, + Variable { + result_type_id: u32, + result_id: u32, + storage_class: StorageClass, + initializer: Option, + }, + Decorate { + target_id: u32, + decoration: Decoration, + params: Vec, + }, + MemberDecorate { + target_id: u32, + member: u32, + decoration: Decoration, + params: Vec, + }, Label { result_id: u32 }, Branch { result_id: u32 }, Kill, @@ -130,84 +196,158 @@ fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> { return Err(ParseError::IncompleteInstruction); } - let opcode = try!(decode_instruction(opcode, &i[1 .. word_count])); - Ok((opcode, &i[word_count..])) + let opcode = decode_instruction(opcode, &i[1 .. word_count])?; + Ok((opcode, &i[word_count ..])) } fn decode_instruction(opcode: u16, operands: &[u32]) -> Result { Ok(match opcode { - 0 => Instruction::Nop, - 5 => Instruction::Name { target_id: operands[0], name: parse_string(&operands[1..]).0 }, - 6 => Instruction::MemberName { target_id: operands[0], member: operands[1], name: parse_string(&operands[2..]).0 }, - 11 => Instruction::ExtInstImport { - result_id: operands[0], - name: parse_string(&operands[1..]).0 - }, - 14 => Instruction::MemoryModel(try!(AddressingModel::from_num(operands[0])), try!(MemoryModel::from_num(operands[1]))), - 15 => { - let (n, r) = parse_string(&operands[2..]); - Instruction::EntryPoint { - execution: try!(ExecutionModel::from_num(operands[0])), - id: operands[1], - name: n, - interface: r.to_owned(), - } - }, - 17 => Instruction::Capability(try!(Capability::from_num(operands[0]))), - 19 => Instruction::TypeVoid { result_id: operands[0] }, - 20 => Instruction::TypeBool { result_id: operands[0] }, - 21 => Instruction::TypeInt { result_id: operands[0], width: operands[1], signedness: operands[2] != 0 }, - 22 => Instruction::TypeFloat { result_id: operands[0], width: operands[1] }, - 23 => Instruction::TypeVector { result_id: operands[0], component_id: operands[1], count: operands[2] }, - 24 => Instruction::TypeMatrix { result_id: operands[0], column_type_id: operands[1], column_count: operands[2] }, - 25 => Instruction::TypeImage { - result_id: operands[0], - sampled_type_id: operands[1], - dim: try!(Dim::from_num(operands[2])), - depth: match operands[3] { 0 => Some(false), 1 => Some(true), 2 => None, _ => unreachable!() }, - arrayed: operands[4] != 0, - ms: operands[5] != 0, - sampled: match operands[6] { 0 => None, 1 => Some(true), 2 => Some(false), _ => unreachable!() }, - format: try!(ImageFormat::from_num(operands[7])), - access: if operands.len() >= 9 { Some(try!(AccessQualifier::from_num(operands[8]))) } else { None }, - }, - 26 => Instruction::TypeSampler { result_id: operands[0] }, - 27 => Instruction::TypeSampledImage { result_id: operands[0], image_type_id: operands[1] }, - 28 => Instruction::TypeArray { result_id: operands[0], type_id: operands[1], length_id: operands[2] }, - 29 => Instruction::TypeRuntimeArray { result_id: operands[0], type_id: operands[1] }, - 30 => Instruction::TypeStruct { result_id: operands[0], member_types: operands[1..].to_owned() }, - 31 => Instruction::TypeOpaque { result_id: operands[0], name: parse_string(&operands[1..]).0 }, - 32 => Instruction::TypePointer { result_id: operands[0], storage_class: try!(StorageClass::from_num(operands[1])), type_id: operands[2] }, - 43 => Instruction::Constant { result_type_id: operands[0], result_id: operands[1], data: operands[2..].to_owned() }, - 56 => Instruction::FunctionEnd, - 59 => Instruction::Variable { - result_type_id: operands[0], result_id: operands[1], - storage_class: try!(StorageClass::from_num(operands[2])), - initializer: operands.get(3).map(|&v| v) - }, - 71 => Instruction::Decorate { target_id: operands[0], decoration: try!(Decoration::from_num(operands[1])), params: operands[2..].to_owned() }, - 72 => Instruction::MemberDecorate { target_id: operands[0], member: operands[1], decoration: try!(Decoration::from_num(operands[2])), params: operands[3..].to_owned() }, - 248 => Instruction::Label { result_id: operands[0] }, - 249 => Instruction::Branch { result_id: operands[0] }, - 252 => Instruction::Kill, - 253 => Instruction::Return, - _ => Instruction::Unknown(opcode, operands.to_owned()), - }) + 0 => Instruction::Nop, + 5 => Instruction::Name { + target_id: operands[0], + name: parse_string(&operands[1 ..]).0, + }, + 6 => Instruction::MemberName { + target_id: operands[0], + member: operands[1], + name: parse_string(&operands[2 ..]).0, + }, + 11 => Instruction::ExtInstImport { + result_id: operands[0], + name: parse_string(&operands[1 ..]).0, + }, + 14 => Instruction::MemoryModel(AddressingModel::from_num(operands[0])?, + MemoryModel::from_num(operands[1])?), + 15 => { + let (n, r) = parse_string(&operands[2 ..]); + Instruction::EntryPoint { + execution: ExecutionModel::from_num(operands[0])?, + id: operands[1], + name: n, + interface: r.to_owned(), + } + }, + 17 => Instruction::Capability(Capability::from_num(operands[0])?), + 19 => Instruction::TypeVoid { result_id: operands[0] }, + 20 => Instruction::TypeBool { result_id: operands[0] }, + 21 => Instruction::TypeInt { + result_id: operands[0], + width: operands[1], + signedness: operands[2] != 0, + }, + 22 => Instruction::TypeFloat { + result_id: operands[0], + width: operands[1], + }, + 23 => Instruction::TypeVector { + result_id: operands[0], + component_id: operands[1], + count: operands[2], + }, + 24 => Instruction::TypeMatrix { + result_id: operands[0], + column_type_id: operands[1], + column_count: operands[2], + }, + 25 => Instruction::TypeImage { + result_id: operands[0], + sampled_type_id: operands[1], + dim: Dim::from_num(operands[2])?, + depth: match operands[3] { + 0 => Some(false), + 1 => Some(true), + 2 => None, + _ => unreachable!(), + }, + arrayed: operands[4] != 0, + ms: operands[5] != 0, + sampled: match operands[6] { + 0 => None, + 1 => Some(true), + 2 => Some(false), + _ => unreachable!(), + }, + format: ImageFormat::from_num(operands[7])?, + access: if operands.len() >= 9 { + Some(AccessQualifier::from_num(operands[8])?) + } else { + None + }, + }, + 26 => Instruction::TypeSampler { result_id: operands[0] }, + 27 => Instruction::TypeSampledImage { + result_id: operands[0], + image_type_id: operands[1], + }, + 28 => Instruction::TypeArray { + result_id: operands[0], + type_id: operands[1], + length_id: operands[2], + }, + 29 => Instruction::TypeRuntimeArray { + result_id: operands[0], + type_id: operands[1], + }, + 30 => Instruction::TypeStruct { + result_id: operands[0], + member_types: operands[1 ..].to_owned(), + }, + 31 => Instruction::TypeOpaque { + result_id: operands[0], + name: parse_string(&operands[1 ..]).0, + }, + 32 => Instruction::TypePointer { + result_id: operands[0], + storage_class: StorageClass::from_num(operands[1])?, + type_id: operands[2], + }, + 43 => Instruction::Constant { + result_type_id: operands[0], + result_id: operands[1], + data: operands[2 ..].to_owned(), + }, + 56 => Instruction::FunctionEnd, + 59 => Instruction::Variable { + result_type_id: operands[0], + result_id: operands[1], + storage_class: StorageClass::from_num(operands[2])?, + initializer: operands.get(3).map(|&v| v), + }, + 71 => Instruction::Decorate { + target_id: operands[0], + decoration: Decoration::from_num(operands[1])?, + params: operands[2 ..].to_owned(), + }, + 72 => Instruction::MemberDecorate { + target_id: operands[0], + member: operands[1], + decoration: Decoration::from_num(operands[2])?, + params: operands[3 ..].to_owned(), + }, + 248 => Instruction::Label { result_id: operands[0] }, + 249 => Instruction::Branch { result_id: operands[0] }, + 252 => Instruction::Kill, + 253 => Instruction::Return, + _ => Instruction::Unknown(opcode, operands.to_owned()), + }) } fn parse_string(data: &[u32]) -> (String, &[u32]) { - let bytes = data.iter().flat_map(|&n| { - let b1 = (n & 0xff) as u8; - let b2 = ((n >> 8) & 0xff) as u8; - let b3 = ((n >> 16) & 0xff) as u8; - let b4 = ((n >> 24) & 0xff) as u8; - vec![b1, b2, b3, b4].into_iter() - }).take_while(|&b| b != 0).collect::>(); + let bytes = data.iter() + .flat_map(|&n| { + let b1 = (n & 0xff) as u8; + let b2 = ((n >> 8) & 0xff) as u8; + let b3 = ((n >> 16) & 0xff) as u8; + let b4 = ((n >> 24) & 0xff) as u8; + vec![b1, b2, b3, b4].into_iter() + }) + .take_while(|&b| b != 0) + .collect::>(); let r = 1 + bytes.len() / 4; let s = String::from_utf8(bytes).expect("Shader content is not UTF-8"); - (s, &data[r..]) + (s, &data[r ..]) } #[cfg(test)] diff --git a/vulkano-shaders/src/structs.rs b/vulkano-shaders/src/structs.rs index 36539224..3633a3aa 100644 --- a/vulkano-shaders/src/structs.rs +++ b/vulkano-shaders/src/structs.rs @@ -9,8 +9,8 @@ use std::mem; -use parse; use enums; +use parse; /// Translates all the structs that are contained in the SPIR-V document as Rust structs. pub fn write_structs(doc: &parse::Spirv) -> String { @@ -18,12 +18,15 @@ pub fn write_structs(doc: &parse::Spirv) -> String { for instruction in &doc.instructions { match *instruction { - parse::Instruction::TypeStruct { result_id, ref member_types } => { + parse::Instruction::TypeStruct { + result_id, + ref member_types, + } => { let (s, _) = write_struct(doc, result_id, member_types); result.push_str(&s); result.push_str("\n"); }, - _ => () + _ => (), } } @@ -34,7 +37,7 @@ pub fn write_structs(doc: &parse::Spirv) -> String { struct Member { name: String, value: String, - offset: Option + offset: Option, } impl Member { @@ -56,7 +59,7 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> (String, // The members of this struct. let mut rust_members = Vec::with_capacity(members.len()); - + // Padding structs will be named `_paddingN` where `N` is determined by this variable. let mut next_padding_num = 0; @@ -72,35 +75,42 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> (String, // Ignore the whole struct is a member is built in, which includes // `gl_Position` for example. if is_builtin_member(doc, struct_id, num as u32) { - return (String::new(), None); // TODO: is this correct? shouldn't it return a correct struct but with a flag or something? + return (String::new(), None); // TODO: is this correct? shouldn't it return a correct struct but with a flag or something? } // Finding offset of the current member, as requested by the SPIR-V code. - let spirv_offset = doc.instructions.iter().filter_map(|i| { - match *i { - parse::Instruction::MemberDecorate { target_id, member, - decoration: enums::Decoration::DecorationOffset, - ref params } if target_id == struct_id && - member as usize == num => - { - return Some(params[0]); - }, - _ => () - }; + let spirv_offset = doc.instructions + .iter() + .filter_map(|i| { + match *i { + parse::Instruction::MemberDecorate { + target_id, + member, + decoration: enums::Decoration::DecorationOffset, + ref params, + } if target_id == struct_id && member as usize == num => { + return Some(params[0]); + }, + _ => (), + }; - None - }).next(); + None + }) + .next(); // Some structs don't have `Offset` decorations, in the case they are used as local // variables only. Ignoring these. let spirv_offset = match spirv_offset { Some(o) => o as usize, - None => return (String::new(), None) // TODO: shouldn't we return and let the caller ignore it instead? + None => return (String::new(), None), // TODO: shouldn't we return and let the caller ignore it instead? }; // We need to add a dummy field if necessary. { - let current_rust_offset = current_rust_offset.as_mut().expect("Found runtime-sized member in non-final position"); + let current_rust_offset = + current_rust_offset + .as_mut() + .expect("Found runtime-sized member in non-final position"); // Updating current_rust_offset to take the alignment of the next field into account *current_rust_offset = if *current_rust_offset == 0 { @@ -111,12 +121,13 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> (String, if spirv_offset != *current_rust_offset { let diff = spirv_offset.checked_sub(*current_rust_offset).unwrap(); - let padding_num = next_padding_num; next_padding_num += 1; + let padding_num = next_padding_num; + next_padding_num += 1; rust_members.push(Member { - name: format!("_dummy{}", padding_num), - value: format!("[u8; {}]", diff), - offset: None, - }); + name: format!("_dummy{}", padding_num), + value: format!("[u8; {}]", diff), + offset: None, + }); *current_rust_offset += diff; } } @@ -129,81 +140,105 @@ fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> (String, } rust_members.push(Member { - name: member_name.to_owned(), - value: ty, - offset: Some(spirv_offset), - }); + name: member_name.to_owned(), + value: ty, + offset: Some(spirv_offset), + }); } // Try determine the total size of the struct in order to add padding at the end of the struct. - let spirv_req_total_size = doc.instructions.iter().filter_map(|i| { - match *i { - parse::Instruction::Decorate { target_id, - decoration: enums::Decoration::DecorationArrayStride, - ref params } => - { - for inst in doc.instructions.iter() { - match *inst { - parse::Instruction::TypeArray { result_id, type_id, .. } - if result_id == target_id && type_id == struct_id => - { - return Some(params[0]); - }, - parse::Instruction::TypeRuntimeArray { result_id, type_id } - if result_id == target_id && type_id == struct_id => - { - return Some(params[0]); - }, - _ => () - } - } + let spirv_req_total_size = doc.instructions + .iter() + .filter_map(|i| match *i { + parse::Instruction::Decorate { + target_id, + decoration: enums::Decoration::DecorationArrayStride, + ref params, + } => { + for inst in doc.instructions.iter() { + match *inst { + parse::Instruction::TypeArray { + result_id, type_id, .. + } if result_id == target_id && type_id == struct_id => { + return Some(params[0]); + }, + parse::Instruction::TypeRuntimeArray { result_id, type_id } + if result_id == target_id && type_id == struct_id => { + return Some(params[0]); + }, + _ => (), + } + } - None - }, - _ => None - } - }).fold(None, |a, b| if let Some(a) = a { assert_eq!(a, b); Some(a) } else { Some(b) }); + None + }, + _ => None, + }) + .fold(None, |a, b| if let Some(a) = a { + assert_eq!(a, b); + Some(a) + } else { + Some(b) + }); // Adding the final padding members. if let (Some(cur_size), Some(req_size)) = (current_rust_offset, spirv_req_total_size) { let diff = req_size.checked_sub(cur_size as u32).unwrap(); if diff >= 1 { rust_members.push(Member { - name: format!("_dummy{}", next_padding_num), - value: format!("[u8; {}]", diff), - offset: None, - }); + name: format!("_dummy{}", next_padding_num), + value: format!("[u8; {}]", diff), + offset: None, + }); } } - + // We can only implement Clone if there's no unsized member in the struct. let (impl_text, derive_text) = if current_rust_offset.is_some() { - let i = format!("\nimpl Clone for {name} {{\n fn clone(&self) -> Self {{\n \ - {name} {{\n{copies}\n }}\n }}\n}}\n", name = name, - copies = rust_members.iter().map(Member::copy_text).collect::>().join(",\n")); + let i = + format!("\nimpl Clone for {name} {{\n fn clone(&self) -> Self {{\n {name} \ + {{\n{copies}\n }}\n }}\n}}\n", + name = name, + copies = rust_members + .iter() + .map(Member::copy_text) + .collect::>() + .join(",\n")); (i, "#[derive(Copy)]") } else { ("".to_owned(), "") }; - let s = format!("#[repr(C)]{derive_text}\npub struct {name} {{\n{members}\n}} /* total_size: {t:?} */\n{impl_text}", - name = name, - members = rust_members.iter().map(Member::declaration_text).collect::>().join(",\n"), - t = spirv_req_total_size, impl_text = impl_text, derive_text = derive_text); - (s, spirv_req_total_size.map(|sz| sz as usize).or(current_rust_offset)) + let s = format!("#[repr(C)]{derive_text}\npub struct {name} {{\n{members}\n}} /* total_size: \ + {t:?} */\n{impl_text}", + name = name, + members = rust_members + .iter() + .map(Member::declaration_text) + .collect::>() + .join(",\n"), + t = spirv_req_total_size, + impl_text = impl_text, + derive_text = derive_text); + (s, + spirv_req_total_size + .map(|sz| sz as usize) + .or(current_rust_offset)) } /// Returns true if a `BuiltIn` decorator is applied on a struct member. fn is_builtin_member(doc: &parse::Spirv, id: u32, member_id: u32) -> bool { for instruction in &doc.instructions { match *instruction { - parse::Instruction::MemberDecorate { target_id, member, - decoration: enums::Decoration::DecorationBuiltIn, - .. } if target_id == id && member == member_id => - { + parse::Instruction::MemberDecorate { + target_id, + member, + decoration: enums::Decoration::DecorationBuiltIn, + .. + } if target_id == id && member == member_id => { return true; }, - _ => () + _ => (), } } @@ -217,103 +252,182 @@ pub fn type_from_id(doc: &parse::Spirv, searched: u32) -> (String, Option for instruction in doc.instructions.iter() { match instruction { &parse::Instruction::TypeBool { result_id } if result_id == searched => { - #[repr(C)] struct Foo { data: bool, after: u8 } + #[repr(C)] + struct Foo { + data: bool, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("bool".to_owned(), Some(size), mem::align_of::()) + return ("bool".to_owned(), Some(size), mem::align_of::()); }, - &parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => { + &parse::Instruction::TypeInt { + result_id, + width, + signedness, + } if result_id == searched => { match (width, signedness) { (8, true) => { - #[repr(C)] struct Foo { data: i8, after: u8 } + #[repr(C)] + struct Foo { + data: i8, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("i8".to_owned(), Some(size), mem::align_of::()) + return ("i8".to_owned(), Some(size), mem::align_of::()); }, (8, false) => { - #[repr(C)] struct Foo { data: u8, after: u8 } + #[repr(C)] + struct Foo { + data: u8, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("u8".to_owned(), Some(size), mem::align_of::()) + return ("u8".to_owned(), Some(size), mem::align_of::()); }, (16, true) => { - #[repr(C)] struct Foo { data: i16, after: u8 } + #[repr(C)] + struct Foo { + data: i16, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("i16".to_owned(), Some(size), mem::align_of::()) + return ("i16".to_owned(), Some(size), mem::align_of::()); }, (16, false) => { - #[repr(C)] struct Foo { data: u16, after: u8 } + #[repr(C)] + struct Foo { + data: u16, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("u16".to_owned(), Some(size), mem::align_of::()) + return ("u16".to_owned(), Some(size), mem::align_of::()); }, (32, true) => { - #[repr(C)] struct Foo { data: i32, after: u8 } + #[repr(C)] + struct Foo { + data: i32, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("i32".to_owned(), Some(size), mem::align_of::()) + return ("i32".to_owned(), Some(size), mem::align_of::()); }, (32, false) => { - #[repr(C)] struct Foo { data: u32, after: u8 } + #[repr(C)] + struct Foo { + data: u32, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("u32".to_owned(), Some(size), mem::align_of::()) + return ("u32".to_owned(), Some(size), mem::align_of::()); }, (64, true) => { - #[repr(C)] struct Foo { data: i64, after: u8 } + #[repr(C)] + struct Foo { + data: i64, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("i64".to_owned(), Some(size), mem::align_of::()) + return ("i64".to_owned(), Some(size), mem::align_of::()); }, (64, false) => { - #[repr(C)] struct Foo { data: u64, after: u8 } + #[repr(C)] + struct Foo { + data: u64, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("u64".to_owned(), Some(size), mem::align_of::()) + return ("u64".to_owned(), Some(size), mem::align_of::()); }, - _ => panic!("No Rust equivalent for an integer of width {}", width) + _ => panic!("No Rust equivalent for an integer of width {}", width), } }, &parse::Instruction::TypeFloat { result_id, width } if result_id == searched => { match width { 32 => { - #[repr(C)] struct Foo { data: f32, after: u8 } + #[repr(C)] + struct Foo { + data: f32, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("f32".to_owned(), Some(size), mem::align_of::()) + return ("f32".to_owned(), Some(size), mem::align_of::()); }, 64 => { - #[repr(C)] struct Foo { data: f64, after: u8 } + #[repr(C)] + struct Foo { + data: f64, + after: u8, + } let size = unsafe { (&(&*(0 as *const Foo)).after) as *const u8 as usize }; - return ("f64".to_owned(), Some(size), mem::align_of::()) + return ("f64".to_owned(), Some(size), mem::align_of::()); }, - _ => panic!("No Rust equivalent for a floating-point of width {}", width) + _ => panic!("No Rust equivalent for a floating-point of width {}", width), } }, - &parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => { + &parse::Instruction::TypeVector { + result_id, + component_id, + count, + } if result_id == searched => { debug_assert_eq!(mem::align_of::<[u32; 3]>(), mem::align_of::()); let (t, t_size, t_align) = type_from_id(doc, component_id); return (format!("[{}; {}]", t, count), t_size.map(|s| s * count as usize), t_align); }, - &parse::Instruction::TypeMatrix { result_id, column_type_id, column_count } if result_id == searched => { + &parse::Instruction::TypeMatrix { + result_id, + column_type_id, + column_count, + } if result_id == searched => { // FIXME: row-major or column-major debug_assert_eq!(mem::align_of::<[u32; 3]>(), mem::align_of::()); let (t, t_size, t_align) = type_from_id(doc, column_type_id); - return (format!("[{}; {}]", t, column_count), t_size.map(|s| s * column_count as usize), t_align); + return (format!("[{}; {}]", t, column_count), + t_size.map(|s| s * column_count as usize), + t_align); }, - &parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => { + &parse::Instruction::TypeArray { + result_id, + type_id, + length_id, + } if result_id == searched => { debug_assert_eq!(mem::align_of::<[u32; 3]>(), mem::align_of::()); let (t, t_size, t_align) = type_from_id(doc, type_id); - let len = doc.instructions.iter().filter_map(|e| { - match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None } - }).next().expect("failed to find array length"); + let len = doc.instructions + .iter() + .filter_map(|e| match e { + &parse::Instruction::Constant { + result_id, + ref data, + .. + } if result_id == length_id => Some(data.clone()), + _ => None, + }) + .next() + .expect("failed to find array length"); let len = len.iter().rev().fold(0u64, |a, &b| (a << 32) | b as u64); - return (format!("[{}; {}]", t, len), t_size.map(|s| s * len as usize), t_align); // FIXME: + return (format!("[{}; {}]", t, len), t_size.map(|s| s * len as usize), t_align); // FIXME: }, - &parse::Instruction::TypeRuntimeArray { result_id, type_id } if result_id == searched => { + &parse::Instruction::TypeRuntimeArray { result_id, type_id } + if result_id == searched => { debug_assert_eq!(mem::align_of::<[u32; 3]>(), mem::align_of::()); let (t, _, t_align) = type_from_id(doc, type_id); return (format!("[{}]", t), None, t_align); }, - &parse::Instruction::TypeStruct { result_id, ref member_types } if result_id == searched => { + &parse::Instruction::TypeStruct { + result_id, + ref member_types, + } if result_id == searched => { // TODO: take the Offset member decorate into account? let name = ::name_from_id(doc, result_id); let (_, size) = write_struct(doc, result_id, member_types); - let align = member_types.iter().map(|&t| type_from_id(doc, t).2).max().unwrap_or(1); + let align = member_types + .iter() + .map(|&t| type_from_id(doc, t).2) + .max() + .unwrap_or(1); return (name, size, align); }, - _ => () + _ => (), } } diff --git a/vulkano-win/src/lib.rs b/vulkano-win/src/lib.rs index 689105fd..81cf5245 100644 --- a/vulkano-win/src/lib.rs +++ b/vulkano-win/src/lib.rs @@ -22,13 +22,13 @@ use winit::{EventsLoop, WindowBuilder}; use winit::CreationError as WindowCreationError; #[cfg(target_os = "macos")] -use objc::runtime::{YES}; +use cocoa::appkit::{NSView, NSWindow}; #[cfg(target_os = "macos")] use cocoa::base::id as cocoa_id; #[cfg(target_os = "macos")] -use cocoa::appkit::{NSWindow, NSView}; -#[cfg(target_os = "macos")] use metal::*; +#[cfg(target_os = "macos")] +use objc::runtime::YES; #[cfg(target_os = "macos")] use std::mem; @@ -49,23 +49,25 @@ pub fn required_extensions() -> InstanceExtensions { match InstanceExtensions::supported_by_core() { Ok(supported) => supported.intersection(&ideal), - Err(_) => InstanceExtensions::none() + Err(_) => InstanceExtensions::none(), } } pub trait VkSurfaceBuild { - fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc) -> Result; + fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc) + -> Result; } impl VkSurfaceBuild for WindowBuilder { - fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc) -> Result { - let window = try!(self.build(events_loop)); - let surface = try!(unsafe { winit_to_surface(instance, &window) }); + fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc) + -> Result { + let window = self.build(events_loop)?; + let surface = unsafe { winit_to_surface(instance, &window) }?; Ok(Window { - window: window, - surface: surface, - }) + window: window, + surface: surface, + }) } } @@ -135,16 +137,14 @@ impl From for CreationError { } #[cfg(target_os = "android")] -unsafe fn winit_to_surface(instance: Arc, - win: &winit::Window) +unsafe fn winit_to_surface(instance: Arc, win: &winit::Window) -> Result, SurfaceCreationError> { use winit::os::android::WindowExt; Surface::from_anativewindow(instance, win.get_native_window()) } #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))] -unsafe fn winit_to_surface(instance: Arc, - win: &winit::Window) +unsafe fn winit_to_surface(instance: Arc, win: &winit::Window) -> Result, SurfaceCreationError> { use winit::os::unix::WindowExt; match (win.get_wayland_display(), win.get_wayland_surface()) { @@ -158,16 +158,15 @@ unsafe fn winit_to_surface(instance: Arc, win.get_xlib_window().unwrap() as _) } else { Surface::from_xcb(instance, - win.get_xcb_connection().unwrap(), - win.get_xlib_window().unwrap() as _) + win.get_xcb_connection().unwrap(), + win.get_xlib_window().unwrap() as _) } - } + }, } } #[cfg(target_os = "windows")] -unsafe fn winit_to_surface(instance: Arc, - win: &winit::Window) +unsafe fn winit_to_surface(instance: Arc, win: &winit::Window) -> Result, SurfaceCreationError> { use winit::os::windows::WindowExt; Surface::from_hwnd(instance, @@ -177,8 +176,7 @@ unsafe fn winit_to_surface(instance: Arc, #[cfg(target_os = "macos")] unsafe fn winit_to_surface(instance: Arc, win: &winit::Window) - -> Result, SurfaceCreationError> -{ + -> Result, SurfaceCreationError> { use winit::os::macos::WindowExt; unsafe { @@ -192,7 +190,7 @@ unsafe fn winit_to_surface(instance: Arc, win: &winit::Window) let view = wnd.contentView(); view.setWantsLayer(YES); - view.setLayer(mem::transmute(layer.0)); // Bombs here with out of memory + view.setLayer(mem::transmute(layer.0)); // Bombs here with out of memory } Surface::from_macos_moltenvk(instance, win.get_nsview() as *const ()) diff --git a/vulkano/build.rs b/vulkano/build.rs index dce0a24e..e61beab5 100644 --- a/vulkano/build.rs +++ b/vulkano/build.rs @@ -1,22 +1,23 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. -use std::env; - -fn main() { - let target = env::var("TARGET").unwrap(); - if target.contains("apple-darwin") { - println!("cargo:rustc-link-search=framework={}", "/Library/Frameworks"); // TODO: necessary? - println!("cargo:rustc-link-lib=c++"); - println!("cargo:rustc-link-lib=framework=MoltenVK"); - println!("cargo:rustc-link-lib=framework=QuartzCore"); - println!("cargo:rustc-link-lib=framework=Metal"); - println!("cargo:rustc-link-lib=framework=Foundation"); - } -} +use std::env; + +fn main() { + let target = env::var("TARGET").unwrap(); + if target.contains("apple-darwin") { + println!("cargo:rustc-link-search=framework={}", + "/Library/Frameworks"); // TODO: necessary? + println!("cargo:rustc-link-lib=c++"); + println!("cargo:rustc-link-lib=framework=MoltenVK"); + println!("cargo:rustc-link-lib=framework=QuartzCore"); + println!("cargo:rustc-link-lib=framework=Metal"); + println!("cargo:rustc-link-lib=framework=Foundation"); + } +} diff --git a/vulkano/src/buffer/cpu_access.rs b/vulkano/src/buffer/cpu_access.rs index 3ad880bb..7b194b08 100644 --- a/vulkano/src/buffer/cpu_access.rs +++ b/vulkano/src/buffer/cpu_access.rs @@ -8,14 +8,15 @@ // according to those terms. //! Buffer whose content is accessible to the CPU. -//! +//! //! The `CpuAccessibleBuffer` is a basic general-purpose buffer. It can be used in any situation //! but may not perform as well as other buffer types. -//! +//! //! Each access from the CPU or from the GPU locks the whole buffer for either reading or writing. //! You can read the buffer multiple times simultaneously. Trying to read and write simultaneously, //! or write and write simultaneously will block. +use smallvec::SmallVec; use std::marker::PhantomData; use std::mem; use std::ops::Deref; @@ -26,12 +27,11 @@ use std::sync::RwLock; use std::sync::RwLockReadGuard; use std::sync::RwLockWriteGuard; use std::sync::TryLockError; -use smallvec::SmallVec; +use buffer::BufferUsage; use buffer::sys::BufferCreationError; use buffer::sys::SparseLevel; use buffer::sys::UnsafeBuffer; -use buffer::BufferUsage; use buffer::traits::BufferAccess; use buffer::traits::BufferInner; use buffer::traits::TypedBufferAccess; @@ -46,15 +46,17 @@ use memory::pool::MemoryPool; use memory::pool::MemoryPoolAlloc; use memory::pool::StdMemoryPool; use sync::AccessError; -use sync::Sharing; use sync::AccessFlagBits; use sync::PipelineStages; +use sync::Sharing; use OomError; /// Buffer whose content is accessible by the CPU. #[derive(Debug)] -pub struct CpuAccessibleBuffer> where A: MemoryPool { +pub struct CpuAccessibleBuffer> + where A: MemoryPool +{ // Inner content. inner: UnsafeBuffer, @@ -80,21 +82,18 @@ impl CpuAccessibleBuffer { -> Result>, OomError> where I: IntoIterator> { - unsafe { - CpuAccessibleBuffer::raw(device, mem::size_of::(), usage, queue_families) - } + unsafe { CpuAccessibleBuffer::raw(device, mem::size_of::(), usage, queue_families) } } /// Builds a new buffer with some data in it. Only allowed for sized data. pub fn from_data<'a, I>(device: Arc, usage: BufferUsage, queue_families: I, data: T) -> Result>, OomError> where I: IntoIterator>, - T: Content + 'static, + T: Content + 'static { unsafe { - let uninitialized = try!( - CpuAccessibleBuffer::raw(device, mem::size_of::(), usage, queue_families) - ); + let uninitialized = + CpuAccessibleBuffer::raw(device, mem::size_of::(), usage, queue_families)?; // Note that we are in panic-unsafety land here. However a panic should never ever // happen here, so in theory we are safe. @@ -129,9 +128,10 @@ impl CpuAccessibleBuffer<[T]> { Q: IntoIterator> { unsafe { - let uninitialized = try!( - CpuAccessibleBuffer::uninitialized_array(device, data.len(), usage, queue_families) - ); + let uninitialized = CpuAccessibleBuffer::uninitialized_array(device, + data.len(), + usage, + queue_families)?; // Note that we are in panic-unsafety land here. However a panic should never ever // happen here, so in theory we are safe. @@ -154,12 +154,10 @@ impl CpuAccessibleBuffer<[T]> { #[inline] #[deprecated] pub fn array<'a, I>(device: Arc, len: usize, usage: BufferUsage, queue_families: I) - -> Result>, OomError> + -> Result>, OomError> where I: IntoIterator> { - unsafe { - CpuAccessibleBuffer::uninitialized_array(device, len, usage, queue_families) - } + unsafe { CpuAccessibleBuffer::uninitialized_array(device, len, usage, queue_families) } } /// Builds a new buffer. Can be used for arrays. @@ -180,12 +178,15 @@ impl CpuAccessibleBuffer { /// /// You must ensure that the size that you pass is correct for `T`. /// - pub unsafe fn raw<'a, I>(device: Arc, size: usize, usage: BufferUsage, queue_families: I) + pub unsafe fn raw<'a, I>(device: Arc, size: usize, usage: BufferUsage, + queue_families: I) -> Result>, OomError> where I: IntoIterator> { - let queue_families = queue_families.into_iter().map(|f| f.id()) - .collect::>(); + let queue_families = queue_families + .into_iter() + .map(|f| f.id()) + .collect::>(); let (buffer, mem_reqs) = { let sharing = if queue_families.len() >= 2 { @@ -197,33 +198,41 @@ impl CpuAccessibleBuffer { match UnsafeBuffer::new(device.clone(), size, usage, sharing, SparseLevel::none()) { Ok(b) => b, Err(BufferCreationError::OomError(err)) => return Err(err), - Err(_) => unreachable!() // We don't use sparse binding, therefore the other - // errors can't happen + Err(_) => unreachable!(), // We don't use sparse binding, therefore the other + // errors can't happen } }; - let mem_ty = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_host_visible()) - .next().unwrap(); // Vk specs guarantee that this can't fail + let mem_ty = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_host_visible()) + .next() + .unwrap(); // Vk specs guarantee that this can't fail - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Linear)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Linear)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); debug_assert!(mem.mapped_memory().is_some()); - try!(buffer.bind_memory(mem.memory(), mem.offset())); + buffer.bind_memory(mem.memory(), mem.offset())?; Ok(Arc::new(CpuAccessibleBuffer { - inner: buffer, - memory: mem, - access: RwLock::new(()), - queue_families: queue_families, - marker: PhantomData, - })) + inner: buffer, + memory: mem, + access: RwLock::new(()), + queue_families: queue_families, + marker: PhantomData, + })) } } -impl CpuAccessibleBuffer where A: MemoryPool { +impl CpuAccessibleBuffer + where A: MemoryPool +{ /// Returns the device used to create this buffer. #[inline] pub fn device(&self) -> &Arc { @@ -234,13 +243,22 @@ impl CpuAccessibleBuffer where A: MemoryPool { // TODO: use a custom iterator #[inline] pub fn queue_families(&self) -> Vec { - self.queue_families.iter().map(|&num| { - self.device().physical_device().queue_family_by_id(num).unwrap() - }).collect() + self.queue_families + .iter() + .map(|&num| { + self.device() + .physical_device() + .queue_family_by_id(num) + .unwrap() + }) + .collect() } } -impl CpuAccessibleBuffer where T: Content + 'static, A: MemoryPool { +impl CpuAccessibleBuffer + where T: Content + 'static, + A: MemoryPool +{ /// Locks the buffer in order to write its content. /// /// If the buffer is currently in use by the GPU, this function will block until either the @@ -251,15 +269,15 @@ impl CpuAccessibleBuffer where T: Content + 'static, A: Memo /// that uses it will block until you unlock it. #[inline] pub fn read(&self) -> Result, TryLockError>> { - let lock = try!(self.access.try_read()); + let lock = self.access.try_read()?; let offset = self.memory.offset(); let range = offset .. offset + self.inner.size(); Ok(ReadLock { - inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) }, - lock: lock, - }) + inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) }, + lock: lock, + }) } /// Locks the buffer in order to write its content. @@ -272,20 +290,21 @@ impl CpuAccessibleBuffer where T: Content + 'static, A: Memo /// that uses it will block until you unlock it. #[inline] pub fn write(&self) -> Result, TryLockError>> { - let lock = try!(self.access.try_write()); + let lock = self.access.try_write()?; let offset = self.memory.offset(); let range = offset .. offset + self.inner.size(); Ok(WriteLock { - inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) }, - lock: lock, - }) + inner: unsafe { self.memory.mapped_memory().unwrap().read_write(range) }, + lock: lock, + }) } } unsafe impl BufferAccess for CpuAccessibleBuffer - where T: 'static + Send + Sync, A: MemoryPool + where T: 'static + Send + Sync, + A: MemoryPool { #[inline] fn inner(&self) -> BufferInner { @@ -302,7 +321,7 @@ unsafe impl BufferAccess for CpuAccessibleBuffer #[inline] fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> { - Ok(()) // FIXME: + Ok(()) // FIXME: } #[inline] @@ -317,7 +336,8 @@ unsafe impl BufferAccess for CpuAccessibleBuffer } unsafe impl TypedBufferAccess for CpuAccessibleBuffer - where T: 'static + Send + Sync, A: MemoryPool + where T: 'static + Send + Sync, + A: MemoryPool { type Content = T; } @@ -417,7 +437,7 @@ impl<'a, T: ?Sized + 'a> DerefMut for WriteLock<'a, T> { #[cfg(test)] mod tests { - use buffer::{CpuAccessibleBuffer, BufferUsage}; + use buffer::{BufferUsage, CpuAccessibleBuffer}; #[test] fn create_empty_buffer() { @@ -425,6 +445,9 @@ mod tests { const EMPTY: [i32; 0] = []; - let _ = CpuAccessibleBuffer::from_data(device, BufferUsage::all(), Some(queue.family()), EMPTY.iter()); + let _ = CpuAccessibleBuffer::from_data(device, + BufferUsage::all(), + Some(queue.family()), + EMPTY.iter()); } } diff --git a/vulkano/src/buffer/cpu_pool.rs b/vulkano/src/buffer/cpu_pool.rs index 6395b069..b72ab21a 100644 --- a/vulkano/src/buffer/cpu_pool.rs +++ b/vulkano/src/buffer/cpu_pool.rs @@ -7,21 +7,21 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::iter; use std::marker::PhantomData; use std::mem; -use std::sync::atomic::AtomicBool; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; use std::sync::Arc; use std::sync::Mutex; use std::sync::MutexGuard; -use smallvec::SmallVec; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; +use buffer::BufferUsage; use buffer::sys::BufferCreationError; use buffer::sys::SparseLevel; use buffer::sys::UnsafeBuffer; -use buffer::BufferUsage; use buffer::traits::BufferAccess; use buffer::traits::BufferInner; use buffer::traits::TypedBufferAccess; @@ -56,7 +56,9 @@ use OomError; /// The `CpuBufferPool` struct internally contains an `Arc`. You can clone the `CpuBufferPool` for /// a cheap cost, and all the clones will share the same underlying buffer. /// -pub struct CpuBufferPool> where A: MemoryPool { +pub struct CpuBufferPool> + where A: MemoryPool +{ // The device of the pool. device: Arc, @@ -80,7 +82,9 @@ pub struct CpuBufferPool> where A: MemoryPool } // One buffer of the pool. -struct ActualBuffer where A: MemoryPool { +struct ActualBuffer + where A: MemoryPool +{ // Inner content. inner: UnsafeBuffer, @@ -111,7 +115,9 @@ struct ActualBufferSubbuffer { /// A subbuffer allocated from a `CpuBufferPool`. /// /// When this object is destroyed, the subbuffer is automatically reclaimed by the pool. -pub struct CpuBufferPoolSubbuffer where A: MemoryPool { +pub struct CpuBufferPoolSubbuffer + where A: MemoryPool +{ buffer: Arc>, // Index of the subbuffer within `buffer`. @@ -130,9 +136,7 @@ impl CpuBufferPool { -> CpuBufferPool where I: IntoIterator> { - unsafe { - CpuBufferPool::raw(device, mem::size_of::(), usage, queue_families) - } + unsafe { CpuBufferPool::raw(device, mem::size_of::(), usage, queue_families) } } /// Builds a `CpuBufferPool` meant for simple uploads. @@ -148,22 +152,23 @@ impl CpuBufferPool { impl CpuBufferPool<[T]> { #[inline] pub fn array<'a, I>(device: Arc, len: usize, usage: BufferUsage, queue_families: I) - -> CpuBufferPool<[T]> + -> CpuBufferPool<[T]> where I: IntoIterator> { - unsafe { - CpuBufferPool::raw(device, mem::size_of::() * len, usage, queue_families) - } + unsafe { CpuBufferPool::raw(device, mem::size_of::() * len, usage, queue_families) } } } impl CpuBufferPool { - pub unsafe fn raw<'a, I>(device: Arc, one_size: usize, - usage: BufferUsage, queue_families: I) -> CpuBufferPool + pub unsafe fn raw<'a, I>(device: Arc, one_size: usize, usage: BufferUsage, + queue_families: I) + -> CpuBufferPool where I: IntoIterator> { - let queue_families = queue_families.into_iter().map(|f| f.id()) - .collect::>(); + let queue_families = queue_families + .into_iter() + .map(|f| f.id()) + .collect::>(); let pool = Device::standard_pool(&device); @@ -187,7 +192,9 @@ impl CpuBufferPool { } } -impl CpuBufferPool where A: MemoryPool { +impl CpuBufferPool + where A: MemoryPool +{ /// Sets the capacity to `capacity`, or does nothing if the capacity is already higher. /// /// Since this can involve a memory allocation, an `OomError` can happen. @@ -197,9 +204,9 @@ impl CpuBufferPool where A: MemoryPool { // Check current capacity. match *cur_buf { Some(ref buf) if buf.capacity >= capacity => { - return Ok(()) + return Ok(()); }, - _ => () + _ => (), }; self.reset_buf(&mut cur_buf, capacity) @@ -225,11 +232,11 @@ impl CpuBufferPool where A: MemoryPool { None => 3, }; - self.reset_buf(&mut mutex, next_capacity).unwrap(); /* FIXME: error */ + self.reset_buf(&mut mutex, next_capacity).unwrap(); /* FIXME: error */ match self.try_next_impl(&mut mutex, data) { Ok(n) => n, - Err(_) => unreachable!() + Err(_) => unreachable!(), } } @@ -246,7 +253,9 @@ impl CpuBufferPool where A: MemoryPool { } // Creates a new buffer and sets it as current. - fn reset_buf(&self, cur_buf_mutex: &mut MutexGuard>>>, capacity: usize) -> Result<(), OomError> { + fn reset_buf(&self, cur_buf_mutex: &mut MutexGuard>>>, + capacity: usize) + -> Result<(), OomError> { unsafe { let (buffer, mem_reqs) = { let sharing = if self.queue_families.len() >= 2 { @@ -260,41 +269,52 @@ impl CpuBufferPool where A: MemoryPool { None => return Err(OomError::OutOfDeviceMemory), }; - match UnsafeBuffer::new(self.device.clone(), total_size, self.usage, sharing, SparseLevel::none()) { + match UnsafeBuffer::new(self.device.clone(), + total_size, + self.usage, + sharing, + SparseLevel::none()) { Ok(b) => b, Err(BufferCreationError::OomError(err)) => return Err(err), - Err(_) => unreachable!() // We don't use sparse binding, therefore the other - // errors can't happen + Err(_) => unreachable!(), // We don't use sparse binding, therefore the other + // errors can't happen } }; - let mem_ty = self.device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_host_visible()) - .next().unwrap(); // Vk specs guarantee that this can't fail + let mem_ty = self.device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_host_visible()) + .next() + .unwrap(); // Vk specs guarantee that this can't fail - let mem = try!(MemoryPool::alloc(&self.pool, mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Linear)); + let mem = MemoryPool::alloc(&self.pool, + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Linear)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); debug_assert!(mem.mapped_memory().is_some()); - try!(buffer.bind_memory(mem.memory(), mem.offset())); + buffer.bind_memory(mem.memory(), mem.offset())?; - **cur_buf_mutex = Some(Arc::new(ActualBuffer { - inner: buffer, - memory: mem, - subbuffers: { - let mut v = Vec::with_capacity(capacity); - for _ in 0 .. capacity { - v.push(ActualBufferSubbuffer { - num_cpu_accesses: AtomicUsize::new(0), - num_gpu_accesses: AtomicUsize::new(0), - }); - } - v - }, - capacity: capacity, - next_subbuffer: AtomicUsize::new(0), - })); + **cur_buf_mutex = + Some(Arc::new(ActualBuffer { + inner: buffer, + memory: mem, + subbuffers: { + let mut v = Vec::with_capacity(capacity); + for _ in 0 .. capacity { + v.push(ActualBufferSubbuffer { + num_cpu_accesses: AtomicUsize::new(0), + num_gpu_accesses: AtomicUsize::new(0), + }); + } + v + }, + capacity: capacity, + next_subbuffer: AtomicUsize::new(0), + })); Ok(()) } @@ -302,12 +322,11 @@ impl CpuBufferPool where A: MemoryPool { // Tries to lock a subbuffer from the current buffer. fn try_next_impl(&self, cur_buf_mutex: &mut MutexGuard>>>, data: T) - -> Result, T> - { + -> Result, T> { // Grab the current buffer. Return `Err` if the pool wasn't "initialized" yet. let current_buffer = match cur_buf_mutex.clone() { Some(b) => b, - None => return Err(data) + None => return Err(data), }; // Grab the next subbuffer to use. @@ -315,38 +334,51 @@ impl CpuBufferPool where A: MemoryPool { // Since the only place that touches `next_subbuffer` is this code, and since we own a // mutex lock to the buffer, it means that `next_subbuffer` can't be accessed // concurrently. - let val = current_buffer.next_subbuffer.fetch_add(1, Ordering::Relaxed); + let val = current_buffer + .next_subbuffer + .fetch_add(1, Ordering::Relaxed); // TODO: handle overflows? // TODO: rewrite this in a proper way by holding an intermediary struct in the mutex instead of the Arc directly val % current_buffer.capacity }; // Check if subbuffer is already taken. If so, the pool is full. - if current_buffer.subbuffers[next_subbuffer].num_cpu_accesses.compare_and_swap(0, 1, Ordering::SeqCst) != 0 { + if current_buffer.subbuffers[next_subbuffer] + .num_cpu_accesses + .compare_and_swap(0, 1, Ordering::SeqCst) != 0 + { return Err(data); } // Reset num_gpu_accesses. - current_buffer.subbuffers[next_subbuffer].num_gpu_accesses.store(0, Ordering::SeqCst); + current_buffer.subbuffers[next_subbuffer] + .num_gpu_accesses + .store(0, Ordering::SeqCst); // Write `data` in the memory. unsafe { let range = (next_subbuffer * self.one_size) .. ((next_subbuffer + 1) * self.one_size); - let mut mapping = current_buffer.memory.mapped_memory().unwrap().read_write(range); + let mut mapping = current_buffer + .memory + .mapped_memory() + .unwrap() + .read_write(range); *mapping = data; } Ok(CpuBufferPoolSubbuffer { - buffer: current_buffer, - subbuffer_index: next_subbuffer, - size: self.one_size, - marker: PhantomData, - }) + buffer: current_buffer, + subbuffer_index: next_subbuffer, + size: self.one_size, + marker: PhantomData, + }) } } // Can't automatically derive `Clone`, otherwise the compiler adds a `T: Clone` requirement. -impl Clone for CpuBufferPool where A: MemoryPool + Clone { +impl Clone for CpuBufferPool + where A: MemoryPool + Clone +{ fn clone(&self) -> Self { let buf = self.current_buffer.lock().unwrap(); @@ -371,9 +403,13 @@ unsafe impl DeviceOwned for CpuBufferPool } } -impl Clone for CpuBufferPoolSubbuffer where A: MemoryPool { +impl Clone for CpuBufferPoolSubbuffer + where A: MemoryPool +{ fn clone(&self) -> CpuBufferPoolSubbuffer { - let old_val = self.buffer.subbuffers[self.subbuffer_index].num_cpu_accesses.fetch_add(1, Ordering::SeqCst); + let old_val = self.buffer.subbuffers[self.subbuffer_index] + .num_cpu_accesses + .fetch_add(1, Ordering::SeqCst); debug_assert!(old_val >= 1); CpuBufferPoolSubbuffer { @@ -458,8 +494,8 @@ unsafe impl DeviceOwned for CpuBufferPoolSubbuffer #[cfg(test)] mod tests { - use std::mem; use buffer::CpuBufferPool; + use std::mem; #[test] fn basic_create() { diff --git a/vulkano/src/buffer/device_local.rs b/vulkano/src/buffer/device_local.rs index 37a2c364..d351ca30 100644 --- a/vulkano/src/buffer/device_local.rs +++ b/vulkano/src/buffer/device_local.rs @@ -13,16 +13,16 @@ //! You can read the buffer multiple times simultaneously from multiple queues. Trying to read and //! write simultaneously, or write and write simultaneously will block with a semaphore. +use smallvec::SmallVec; use std::marker::PhantomData; use std::mem; use std::sync::Arc; use std::sync::atomic::AtomicUsize; -use smallvec::SmallVec; +use buffer::BufferUsage; use buffer::sys::BufferCreationError; use buffer::sys::SparseLevel; use buffer::sys::UnsafeBuffer; -use buffer::BufferUsage; use buffer::traits::BufferAccess; use buffer::traits::BufferInner; use buffer::traits::TypedBufferAccess; @@ -42,7 +42,9 @@ use SafeDeref; /// Buffer whose content is accessible by the CPU. #[derive(Debug)] -pub struct DeviceLocalBuffer> where A: MemoryPool { +pub struct DeviceLocalBuffer> + where A: MemoryPool +{ // Inner content. inner: UnsafeBuffer, @@ -66,9 +68,7 @@ impl DeviceLocalBuffer { -> Result>, OomError> where I: IntoIterator> { - unsafe { - DeviceLocalBuffer::raw(device, mem::size_of::(), usage, queue_families) - } + unsafe { DeviceLocalBuffer::raw(device, mem::size_of::(), usage, queue_families) } } } @@ -76,12 +76,10 @@ impl DeviceLocalBuffer<[T]> { /// Builds a new buffer. Can be used for arrays. #[inline] pub fn array<'a, I>(device: Arc, len: usize, usage: BufferUsage, queue_families: I) - -> Result>, OomError> + -> Result>, OomError> where I: IntoIterator> { - unsafe { - DeviceLocalBuffer::raw(device, len * mem::size_of::(), usage, queue_families) - } + unsafe { DeviceLocalBuffer::raw(device, len * mem::size_of::(), usage, queue_families) } } } @@ -92,12 +90,15 @@ impl DeviceLocalBuffer { /// /// You must ensure that the size that you pass is correct for `T`. /// - pub unsafe fn raw<'a, I>(device: Arc, size: usize, usage: BufferUsage, queue_families: I) + pub unsafe fn raw<'a, I>(device: Arc, size: usize, usage: BufferUsage, + queue_families: I) -> Result>, OomError> where I: IntoIterator> { - let queue_families = queue_families.into_iter().map(|f| f.id()) - .collect::>(); + let queue_families = queue_families + .into_iter() + .map(|f| f.id()) + .collect::>(); let (buffer, mem_reqs) = { let sharing = if queue_families.len() >= 2 { @@ -109,36 +110,45 @@ impl DeviceLocalBuffer { match UnsafeBuffer::new(device.clone(), size, usage, sharing, SparseLevel::none()) { Ok(b) => b, Err(BufferCreationError::OomError(err)) => return Err(err), - Err(_) => unreachable!() // We don't use sparse binding, therefore the other - // errors can't happen + Err(_) => unreachable!(), // We don't use sparse binding, therefore the other + // errors can't happen } }; let mem_ty = { - let device_local = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_device_local()); - let any = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); + let device_local = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_device_local()); + let any = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); device_local.chain(any).next().unwrap() }; - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Linear)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Linear)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); - try!(buffer.bind_memory(mem.memory(), mem.offset())); + buffer.bind_memory(mem.memory(), mem.offset())?; Ok(Arc::new(DeviceLocalBuffer { - inner: buffer, - memory: mem, - queue_families: queue_families, - gpu_lock: AtomicUsize::new(0), - marker: PhantomData, - })) + inner: buffer, + memory: mem, + queue_families: queue_families, + gpu_lock: AtomicUsize::new(0), + marker: PhantomData, + })) } } -impl DeviceLocalBuffer where A: MemoryPool { +impl DeviceLocalBuffer + where A: MemoryPool +{ /// Returns the device used to create this buffer. #[inline] pub fn device(&self) -> &Arc { @@ -149,9 +159,15 @@ impl DeviceLocalBuffer where A: MemoryPool { // TODO: use a custom iterator #[inline] pub fn queue_families(&self) -> Vec { - self.queue_families.iter().map(|&num| { - self.device().physical_device().queue_family_by_id(num).unwrap() - }).collect() + self.queue_families + .iter() + .map(|&num| { + self.device() + .physical_device() + .queue_family_by_id(num) + .unwrap() + }) + .collect() } } diff --git a/vulkano/src/buffer/immutable.rs b/vulkano/src/buffer/immutable.rs index b88e568c..bf580ba4 100644 --- a/vulkano/src/buffer/immutable.rs +++ b/vulkano/src/buffer/immutable.rs @@ -8,34 +8,34 @@ // according to those terms. //! Buffer that is written once then read for as long as it is alive. -//! +//! //! Use this buffer when you have data that you never modify. //! //! Only the first ever command buffer that uses this buffer can write to it (for example by //! copying from another buffer). Any subsequent command buffer **must** only read from the buffer, //! or a panic will happen. -//! +//! //! The buffer will be stored in device-local memory if possible //! +use smallvec::SmallVec; use std::iter; use std::marker::PhantomData; use std::mem; use std::sync::Arc; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; -use smallvec::SmallVec; +use buffer::BufferUsage; use buffer::CpuAccessibleBuffer; use buffer::sys::BufferCreationError; use buffer::sys::SparseLevel; use buffer::sys::UnsafeBuffer; -use buffer::BufferUsage; use buffer::traits::BufferAccess; use buffer::traits::BufferInner; use buffer::traits::TypedBufferAccess; -use command_buffer::AutoCommandBufferBuilder; use command_buffer::AutoCommandBuffer; +use command_buffer::AutoCommandBufferBuilder; use command_buffer::CommandBuffer; use command_buffer::CommandBufferExecFuture; use device::Device; @@ -86,13 +86,16 @@ impl ImmutableBuffer { /// the initial upload operation. In order to be allowed to use the `ImmutableBuffer`, you must /// either submit your operation after this future, or execute this future and wait for it to /// be finished before submitting your own operation. - pub fn from_data<'a, I>(data: T, usage: BufferUsage, queue_families: I, queue: Arc) - -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> + pub fn from_data<'a, I>( + data: T, usage: BufferUsage, queue_families: I, queue: Arc) + -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> where I: IntoIterator>, - T: 'static + Send + Sync + Sized, + T: 'static + Send + Sync + Sized { - let source = CpuAccessibleBuffer::from_data(queue.device().clone(), BufferUsage::transfer_source(), - iter::once(queue.family()), data)?; + let source = CpuAccessibleBuffer::from_data(queue.device().clone(), + BufferUsage::transfer_source(), + iter::once(queue.family()), + data)?; ImmutableBuffer::from_buffer(source, usage, queue_families, queue) } @@ -102,21 +105,24 @@ impl ImmutableBuffer { /// the initial upload operation. In order to be allowed to use the `ImmutableBuffer`, you must /// either submit your operation after this future, or execute this future and wait for it to /// be finished before submitting your own operation. - pub fn from_buffer<'a, B, I>(source: B, usage: BufferUsage, queue_families: I, queue: Arc) - -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> + pub fn from_buffer<'a, B, I>( + source: B, usage: BufferUsage, queue_families: I, queue: Arc) + -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> where B: BufferAccess + TypedBufferAccess + 'static + Clone + Send + Sync, I: IntoIterator>, - T: 'static + Send + Sync, + T: 'static + Send + Sync { unsafe { // We automatically set `transfer_dest` to true in order to avoid annoying errors. let actual_usage = BufferUsage { transfer_dest: true, - .. usage + ..usage }; - let (buffer, init) = ImmutableBuffer::raw(source.device().clone(), source.size(), - actual_usage, queue_families)?; + let (buffer, init) = ImmutableBuffer::raw(source.device().clone(), + source.size(), + actual_usage, + queue_families)?; let cb = AutoCommandBufferBuilder::new(source.device().clone(), queue.family())? .copy_buffer(source, init).unwrap() // TODO: return error? @@ -124,7 +130,7 @@ impl ImmutableBuffer { let future = match cb.execute(queue) { Ok(f) => f, - Err(_) => unreachable!() + Err(_) => unreachable!(), }; Ok((buffer, future)) @@ -150,8 +156,9 @@ impl ImmutableBuffer { /// data, otherwise the content is undefined. /// #[inline] - pub unsafe fn uninitialized<'a, I>(device: Arc, usage: BufferUsage, queue_families: I) - -> Result<(Arc>, ImmutableBufferInitialization), OomError> + pub unsafe fn uninitialized<'a, I>( + device: Arc, usage: BufferUsage, queue_families: I) + -> Result<(Arc>, ImmutableBufferInitialization), OomError> where I: IntoIterator> { ImmutableBuffer::raw(device, mem::size_of::(), usage, queue_families) @@ -159,14 +166,17 @@ impl ImmutableBuffer { } impl ImmutableBuffer<[T]> { - pub fn from_iter<'a, D, I>(data: D, usage: BufferUsage, queue_families: I, queue: Arc) - -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> + pub fn from_iter<'a, D, I>( + data: D, usage: BufferUsage, queue_families: I, queue: Arc) + -> Result<(Arc>, ImmutableBufferFromBufferFuture), OomError> where I: IntoIterator>, D: ExactSizeIterator, - T: 'static + Send + Sync + Sized, + T: 'static + Send + Sync + Sized { - let source = CpuAccessibleBuffer::from_iter(queue.device().clone(), BufferUsage::transfer_source(), - iter::once(queue.family()), data)?; + let source = CpuAccessibleBuffer::from_iter(queue.device().clone(), + BufferUsage::transfer_source(), + iter::once(queue.family()), + data)?; ImmutableBuffer::from_buffer(source, usage, queue_families, queue) } @@ -187,9 +197,9 @@ impl ImmutableBuffer<[T]> { /// data, otherwise the content is undefined. /// #[inline] - pub unsafe fn uninitialized_array<'a, I>(device: Arc, len: usize, usage: BufferUsage, - queue_families: I) - -> Result<(Arc>, ImmutableBufferInitialization<[T]>), OomError> + pub unsafe fn uninitialized_array<'a, I>( + device: Arc, len: usize, usage: BufferUsage, queue_families: I) + -> Result<(Arc>, ImmutableBufferInitialization<[T]>), OomError> where I: IntoIterator> { ImmutableBuffer::raw(device, len * mem::size_of::(), usage, queue_families) @@ -213,8 +223,9 @@ impl ImmutableBuffer { /// data. /// #[inline] - pub unsafe fn raw<'a, I>(device: Arc, size: usize, usage: BufferUsage, queue_families: I) - -> Result<(Arc>, ImmutableBufferInitialization), OomError> + pub unsafe fn raw<'a, I>( + device: Arc, size: usize, usage: BufferUsage, queue_families: I) + -> Result<(Arc>, ImmutableBufferInitialization), OomError> where I: IntoIterator> { let queue_families = queue_families.into_iter().map(|f| f.id()).collect(); @@ -223,10 +234,9 @@ impl ImmutableBuffer { // Internal implementation of `raw`. This is separated from `raw` so that it doesn't need to be // inlined. - unsafe fn raw_impl(device: Arc, size: usize, usage: BufferUsage, - queue_families: SmallVec<[u32; 4]>) - -> Result<(Arc>, ImmutableBufferInitialization), OomError> - { + unsafe fn raw_impl( + device: Arc, size: usize, usage: BufferUsage, queue_families: SmallVec<[u32; 4]>) + -> Result<(Arc>, ImmutableBufferInitialization), OomError> { let (buffer, mem_reqs) = { let sharing = if queue_families.len() >= 2 { Sharing::Concurrent(queue_families.iter().cloned()) @@ -237,32 +247,39 @@ impl ImmutableBuffer { match UnsafeBuffer::new(device.clone(), size, usage, sharing, SparseLevel::none()) { Ok(b) => b, Err(BufferCreationError::OomError(err)) => return Err(err), - Err(_) => unreachable!() // We don't use sparse binding, therefore the other - // errors can't happen + Err(_) => unreachable!(), // We don't use sparse binding, therefore the other + // errors can't happen } }; let mem_ty = { - let device_local = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_device_local()); - let any = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); + let device_local = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_device_local()); + let any = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); device_local.chain(any).next().unwrap() }; - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Linear)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Linear)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); - try!(buffer.bind_memory(mem.memory(), mem.offset())); + buffer.bind_memory(mem.memory(), mem.offset())?; let final_buf = Arc::new(ImmutableBuffer { - inner: buffer, - memory: mem, - queue_families: queue_families, - initialized: AtomicBool::new(false), - marker: PhantomData, - }); + inner: buffer, + memory: mem, + queue_families: queue_families, + initialized: AtomicBool::new(false), + marker: PhantomData, + }); let initialization = ImmutableBufferInitialization { buffer: final_buf.clone(), @@ -284,9 +301,15 @@ impl ImmutableBuffer { // TODO: use a custom iterator #[inline] pub fn queue_families(&self) -> Vec { - self.queue_families.iter().map(|&num| { - self.device().physical_device().queue_family_by_id(num).unwrap() - }).collect() + self.queue_families + .iter() + .map(|&num| { + self.device() + .physical_device() + .queue_family_by_id(num) + .unwrap() + }) + .collect() } } @@ -402,30 +425,40 @@ impl Clone for ImmutableBufferInitialization { #[cfg(test)] mod tests { - use std::iter; + use buffer::BufferUsage; use buffer::cpu_access::CpuAccessibleBuffer; use buffer::immutable::ImmutableBuffer; - use buffer::BufferUsage; use command_buffer::AutoCommandBufferBuilder; use command_buffer::CommandBuffer; + use std::iter; use sync::GpuFuture; #[test] fn from_data_working() { let (device, queue) = gfx_dev_and_queue!(); - let (buffer, _) = ImmutableBuffer::from_data(12u32, BufferUsage::all(), + let (buffer, _) = ImmutableBuffer::from_data(12u32, + BufferUsage::all(), iter::once(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); - let dest = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), - iter::once(queue.family()), 0).unwrap(); + let dest = CpuAccessibleBuffer::from_data(device.clone(), + BufferUsage::all(), + iter::once(queue.family()), + 0) + .unwrap(); - let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(buffer, dest.clone()).unwrap() - .build().unwrap() - .execute(queue.clone()).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(buffer, dest.clone()) + .unwrap() + .build() + .unwrap() + .execute(queue.clone()) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); let dest_content = dest.read().unwrap(); assert_eq!(*dest_content, 12); @@ -435,19 +468,28 @@ mod tests { fn from_iter_working() { let (device, queue) = gfx_dev_and_queue!(); - let (buffer, _) = ImmutableBuffer::from_iter((0 .. 512u32).map(|n| n * 2), BufferUsage::all(), + let (buffer, _) = ImmutableBuffer::from_iter((0 .. 512u32).map(|n| n * 2), + BufferUsage::all(), iter::once(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); - let dest = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), + let dest = CpuAccessibleBuffer::from_iter(device.clone(), + BufferUsage::all(), iter::once(queue.family()), - (0 .. 512).map(|_| 0u32)).unwrap(); + (0 .. 512).map(|_| 0u32)) + .unwrap(); - let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(buffer, dest.clone()).unwrap() - .build().unwrap() - .execute(queue.clone()).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(buffer, dest.clone()) + .unwrap() + .build() + .unwrap() + .execute(queue.clone()) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); let dest_content = dest.read().unwrap(); for (n, &v) in dest_content.iter().enumerate() { @@ -456,39 +498,56 @@ mod tests { } #[test] - #[should_panic] // TODO: check Result error instead of panicking + #[should_panic] // TODO: check Result error instead of panicking fn writing_forbidden() { let (device, queue) = gfx_dev_and_queue!(); - let (buffer, _) = ImmutableBuffer::from_data(12u32, BufferUsage::all(), + let (buffer, _) = ImmutableBuffer::from_data(12u32, + BufferUsage::all(), iter::once(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); - let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .fill_buffer(buffer, 50).unwrap() - .build().unwrap() - .execute(queue.clone()).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .fill_buffer(buffer, 50) + .unwrap() + .build() + .unwrap() + .execute(queue.clone()) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); } #[test] - #[should_panic] // TODO: check Result error instead of panicking + #[should_panic] // TODO: check Result error instead of panicking fn read_uninitialized_forbidden() { let (device, queue) = gfx_dev_and_queue!(); let (buffer, _) = unsafe { - ImmutableBuffer::::uninitialized(device.clone(), BufferUsage::all(), - iter::once(queue.family())).unwrap() + ImmutableBuffer::::uninitialized(device.clone(), + BufferUsage::all(), + iter::once(queue.family())) + .unwrap() }; - let src = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), - iter::once(queue.family()), 0).unwrap(); + let src = CpuAccessibleBuffer::from_data(device.clone(), + BufferUsage::all(), + iter::once(queue.family()), + 0) + .unwrap(); - let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(src, buffer).unwrap() - .build().unwrap() - .execute(queue.clone()).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(src, buffer) + .unwrap() + .build() + .unwrap() + .execute(queue.clone()) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); } #[test] @@ -496,52 +555,78 @@ mod tests { let (device, queue) = gfx_dev_and_queue!(); let (buffer, init) = unsafe { - ImmutableBuffer::::uninitialized(device.clone(), BufferUsage::all(), - iter::once(queue.family())).unwrap() + ImmutableBuffer::::uninitialized(device.clone(), + BufferUsage::all(), + iter::once(queue.family())) + .unwrap() }; - let src = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), - iter::once(queue.family()), 0).unwrap(); + let src = CpuAccessibleBuffer::from_data(device.clone(), + BufferUsage::all(), + iter::once(queue.family()), + 0) + .unwrap(); - let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(src.clone(), init).unwrap() - .copy_buffer(buffer, src.clone()).unwrap() - .build().unwrap() - .execute(queue.clone()).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(src.clone(), init) + .unwrap() + .copy_buffer(buffer, src.clone()) + .unwrap() + .build() + .unwrap() + .execute(queue.clone()) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); } #[test] - #[ignore] // TODO: doesn't work because the submit sync layer isn't properly implemented + #[ignore] // TODO: doesn't work because the submit sync layer isn't properly implemented fn init_then_read_same_future() { let (device, queue) = gfx_dev_and_queue!(); let (buffer, init) = unsafe { - ImmutableBuffer::::uninitialized(device.clone(), BufferUsage::all(), - iter::once(queue.family())).unwrap() + ImmutableBuffer::::uninitialized(device.clone(), + BufferUsage::all(), + iter::once(queue.family())) + .unwrap() }; - let src = CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), - iter::once(queue.family()), 0).unwrap(); + let src = CpuAccessibleBuffer::from_data(device.clone(), + BufferUsage::all(), + iter::once(queue.family()), + 0) + .unwrap(); - let cb1 = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(src.clone(), init).unwrap() - .build().unwrap(); + let cb1 = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(src.clone(), init) + .unwrap() + .build() + .unwrap(); - let cb2 = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap() - .copy_buffer(buffer, src.clone()).unwrap() - .build().unwrap(); + let cb2 = AutoCommandBufferBuilder::new(device.clone(), queue.family()) + .unwrap() + .copy_buffer(buffer, src.clone()) + .unwrap() + .build() + .unwrap(); - let _ = cb1.execute(queue.clone()).unwrap() - .then_execute(queue.clone(), cb2).unwrap() - .then_signal_fence_and_flush().unwrap(); + let _ = cb1.execute(queue.clone()) + .unwrap() + .then_execute(queue.clone(), cb2) + .unwrap() + .then_signal_fence_and_flush() + .unwrap(); } #[test] fn create_buffer_zero_size_data() { let (device, queue) = gfx_dev_and_queue!(); - let _ = ImmutableBuffer::from_data((), BufferUsage::all(), Some(queue.family()), queue.clone()); + let _ = + ImmutableBuffer::from_data((), BufferUsage::all(), Some(queue.family()), queue.clone()); } // TODO: write tons of tests that try to exploit loopholes diff --git a/vulkano/src/buffer/slice.rs b/vulkano/src/buffer/slice.rs index 1d87e8e9..49af7196 100644 --- a/vulkano/src/buffer/slice.rs +++ b/vulkano/src/buffer/slice.rs @@ -1,258 +1,266 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. -use std::marker::PhantomData; -use std::mem; -use std::ops::Range; -use std::sync::Arc; +use std::marker::PhantomData; +use std::mem; +use std::ops::Range; +use std::sync::Arc; -use buffer::traits::BufferAccess; -use buffer::traits::BufferInner; -use buffer::traits::TypedBufferAccess; -use device::Device; -use device::DeviceOwned; -use device::Queue; -use sync::AccessError; - -/// A subpart of a buffer. -/// -/// This object doesn't correspond to any Vulkan object. It exists for API convenience. -/// -/// # Example -/// -/// Creating a slice: -/// -/// ```ignore // FIXME: unignore -/// use vulkano::buffer::BufferSlice; -/// # let buffer: std::sync::Arc> = return; -/// let _slice = BufferSlice::from(&buffer); -/// ``` -/// -/// Selecting a slice of a buffer that contains `[T]`: -/// -/// ```ignore // FIXME: unignore -/// use vulkano::buffer::BufferSlice; -/// # let buffer: std::sync::Arc> = return; -/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap(); -/// ``` -/// -pub struct BufferSlice { - marker: PhantomData, - resource: B, - offset: usize, - size: usize, -} - -// We need to implement `Clone` manually, otherwise the derive adds a `T: Clone` requirement. -impl Clone for BufferSlice - where B: Clone -{ - #[inline] - fn clone(&self) -> Self { - BufferSlice { - marker: PhantomData, - resource: self.resource.clone(), - offset: self.offset, - size: self.size, - } - } -} - -impl BufferSlice { - #[inline] - pub fn from_typed_buffer_access(r: B) -> BufferSlice - where B: TypedBufferAccess - { - let size = r.size(); - - BufferSlice { - marker: PhantomData, - resource: r, - offset: 0, - size: size, - } - } - - /// Returns the buffer that this slice belongs to. - pub fn buffer(&self) -> &B { - &self.resource - } - - /// Returns the offset of that slice within the buffer. - #[inline] - pub fn offset(&self) -> usize { - self.offset - } - - /// Returns the size of that slice in bytes. - #[inline] - pub fn size(&self) -> usize { - self.size - } - - /// Builds a slice that contains an element from inside the buffer. - /// - /// This method builds an object that represents a slice of the buffer. No actual operation - /// is performed. - /// - /// # Example - /// - /// TODO - /// - /// # Safety - /// - /// The object whose reference is passed to the closure is uninitialized. Therefore you - /// **must not** access the content of the object. - /// - /// You **must** return a reference to an element from the parameter. The closure **must not** - /// panic. - #[inline] - pub unsafe fn slice_custom(self, f: F) -> BufferSlice - where F: for<'r> FnOnce(&'r T) -> &'r R - // TODO: bounds on R - { - let data: &T = mem::zeroed(); - let result = f(data); - let size = mem::size_of_val(result); - let result = result as *const R as *const () as usize; - - assert!(result <= self.size()); - assert!(result + size <= self.size()); - - BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + result, - size: size, - } - } -} - -impl BufferSlice<[T], B> { - /// Returns the number of elements in this slice. - #[inline] - pub fn len(&self) -> usize { - debug_assert_eq!(self.size() % mem::size_of::(), 0); - self.size() / mem::size_of::() - } - - /// Reduces the slice to just one element of the array. - /// - /// Returns `None` if out of range. - #[inline] - pub fn index(self, index: usize) -> Option> { - if index >= self.len() { return None; } - - Some(BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + index * mem::size_of::(), - size: mem::size_of::(), - }) - } - - /// Reduces the slice to just a range of the array. - /// - /// Returns `None` if out of range. - #[inline] - pub fn slice(self, range: Range) -> Option> { - if range.end > self.len() { return None; } - - Some(BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + range.start * mem::size_of::(), - size: (range.end - range.start) * mem::size_of::(), - }) - } -} - -unsafe impl BufferAccess for BufferSlice where B: BufferAccess { - #[inline] - fn inner(&self) -> BufferInner { - let inner = self.resource.inner(); - BufferInner { - buffer: inner.buffer, - offset: inner.offset + self.offset, - } - } - - #[inline] - fn size(&self) -> usize { - self.size - } - - #[inline] - fn conflicts_buffer(&self, self_offset: usize, self_size: usize, - other: &BufferAccess, other_offset: usize, other_size: usize) -> bool - { - let self_offset = self.offset + self_offset; - // FIXME: spurious failures ; needs investigation - //debug_assert!(self_size + self_offset <= self.size); - self.resource.conflicts_buffer(self_offset, self_size, other, other_offset, other_size) - } - - #[inline] - fn conflict_key(&self, self_offset: usize, self_size: usize) -> u64 { - let self_offset = self.offset + self_offset; - // FIXME: spurious failures ; needs investigation - //debug_assert!(self_size + self_offset <= self.size); - self.resource.conflict_key(self_offset, self_size) - } - - #[inline] - fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> { - self.resource.try_gpu_lock(exclusive_access, queue) - } - - #[inline] - unsafe fn increase_gpu_lock(&self) { - self.resource.increase_gpu_lock() - } - - #[inline] - unsafe fn unlock(&self) { - self.resource.unlock() - } -} - -unsafe impl TypedBufferAccess for BufferSlice where B: BufferAccess, { - type Content = T; -} - -unsafe impl DeviceOwned for BufferSlice - where B: DeviceOwned -{ - #[inline] - fn device(&self) -> &Arc { - self.resource.device() - } -} - -impl From> for BufferSlice<[T], B> { - #[inline] - fn from(r: BufferSlice) -> BufferSlice<[T], B> { - BufferSlice { - marker: PhantomData, - resource: r.resource, - offset: r.offset, - size: r.size, - } - } -} - -/// Takes a `BufferSlice` that points to a struct, and returns a `BufferSlice` that points to -/// a specific field of that struct. -#[macro_export] +use buffer::traits::BufferAccess; +use buffer::traits::BufferInner; +use buffer::traits::TypedBufferAccess; +use device::Device; +use device::DeviceOwned; +use device::Queue; +use sync::AccessError; + +/// A subpart of a buffer. +/// +/// This object doesn't correspond to any Vulkan object. It exists for API convenience. +/// +/// # Example +/// +/// Creating a slice: +/// +/// ```ignore // FIXME: unignore +/// use vulkano::buffer::BufferSlice; +/// # let buffer: std::sync::Arc> = return; +/// let _slice = BufferSlice::from(&buffer); +/// ``` +/// +/// Selecting a slice of a buffer that contains `[T]`: +/// +/// ```ignore // FIXME: unignore +/// use vulkano::buffer::BufferSlice; +/// # let buffer: std::sync::Arc> = return; +/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap(); +/// ``` +/// +pub struct BufferSlice { + marker: PhantomData, + resource: B, + offset: usize, + size: usize, +} + +// We need to implement `Clone` manually, otherwise the derive adds a `T: Clone` requirement. +impl Clone for BufferSlice + where B: Clone +{ + #[inline] + fn clone(&self) -> Self { + BufferSlice { + marker: PhantomData, + resource: self.resource.clone(), + offset: self.offset, + size: self.size, + } + } +} + +impl BufferSlice { + #[inline] + pub fn from_typed_buffer_access(r: B) -> BufferSlice + where B: TypedBufferAccess + { + let size = r.size(); + + BufferSlice { + marker: PhantomData, + resource: r, + offset: 0, + size: size, + } + } + + /// Returns the buffer that this slice belongs to. + pub fn buffer(&self) -> &B { + &self.resource + } + + /// Returns the offset of that slice within the buffer. + #[inline] + pub fn offset(&self) -> usize { + self.offset + } + + /// Returns the size of that slice in bytes. + #[inline] + pub fn size(&self) -> usize { + self.size + } + + /// Builds a slice that contains an element from inside the buffer. + /// + /// This method builds an object that represents a slice of the buffer. No actual operation + /// is performed. + /// + /// # Example + /// + /// TODO + /// + /// # Safety + /// + /// The object whose reference is passed to the closure is uninitialized. Therefore you + /// **must not** access the content of the object. + /// + /// You **must** return a reference to an element from the parameter. The closure **must not** + /// panic. + #[inline] + pub unsafe fn slice_custom(self, f: F) -> BufferSlice + where F: for<'r> FnOnce(&'r T) -> &'r R // TODO: bounds on R + { + let data: &T = mem::zeroed(); + let result = f(data); + let size = mem::size_of_val(result); + let result = result as *const R as *const () as usize; + + assert!(result <= self.size()); + assert!(result + size <= self.size()); + + BufferSlice { + marker: PhantomData, + resource: self.resource, + offset: self.offset + result, + size: size, + } + } +} + +impl BufferSlice<[T], B> { + /// Returns the number of elements in this slice. + #[inline] + pub fn len(&self) -> usize { + debug_assert_eq!(self.size() % mem::size_of::(), 0); + self.size() / mem::size_of::() + } + + /// Reduces the slice to just one element of the array. + /// + /// Returns `None` if out of range. + #[inline] + pub fn index(self, index: usize) -> Option> { + if index >= self.len() { + return None; + } + + Some(BufferSlice { + marker: PhantomData, + resource: self.resource, + offset: self.offset + index * mem::size_of::(), + size: mem::size_of::(), + }) + } + + /// Reduces the slice to just a range of the array. + /// + /// Returns `None` if out of range. + #[inline] + pub fn slice(self, range: Range) -> Option> { + if range.end > self.len() { + return None; + } + + Some(BufferSlice { + marker: PhantomData, + resource: self.resource, + offset: self.offset + range.start * mem::size_of::(), + size: (range.end - range.start) * mem::size_of::(), + }) + } +} + +unsafe impl BufferAccess for BufferSlice + where B: BufferAccess +{ + #[inline] + fn inner(&self) -> BufferInner { + let inner = self.resource.inner(); + BufferInner { + buffer: inner.buffer, + offset: inner.offset + self.offset, + } + } + + #[inline] + fn size(&self) -> usize { + self.size + } + + #[inline] + fn conflicts_buffer(&self, self_offset: usize, self_size: usize, other: &BufferAccess, + other_offset: usize, other_size: usize) + -> bool { + let self_offset = self.offset + self_offset; + // FIXME: spurious failures ; needs investigation + //debug_assert!(self_size + self_offset <= self.size); + self.resource + .conflicts_buffer(self_offset, self_size, other, other_offset, other_size) + } + + #[inline] + fn conflict_key(&self, self_offset: usize, self_size: usize) -> u64 { + let self_offset = self.offset + self_offset; + // FIXME: spurious failures ; needs investigation + //debug_assert!(self_size + self_offset <= self.size); + self.resource.conflict_key(self_offset, self_size) + } + + #[inline] + fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> { + self.resource.try_gpu_lock(exclusive_access, queue) + } + + #[inline] + unsafe fn increase_gpu_lock(&self) { + self.resource.increase_gpu_lock() + } + + #[inline] + unsafe fn unlock(&self) { + self.resource.unlock() + } +} + +unsafe impl TypedBufferAccess for BufferSlice + where B: BufferAccess +{ + type Content = T; +} + +unsafe impl DeviceOwned for BufferSlice + where B: DeviceOwned +{ + #[inline] + fn device(&self) -> &Arc { + self.resource.device() + } +} + +impl From> for BufferSlice<[T], B> { + #[inline] + fn from(r: BufferSlice) -> BufferSlice<[T], B> { + BufferSlice { + marker: PhantomData, + resource: r.resource, + offset: r.offset, + size: r.size, + } + } +} + +/// Takes a `BufferSlice` that points to a struct, and returns a `BufferSlice` that points to +/// a specific field of that struct. +#[macro_export] macro_rules! buffer_slice_field { ($slice:expr, $field:ident) => ( // TODO: add #[allow(unsafe_code)] when that's allowed unsafe { $slice.slice_custom(|s| &s.$field) } ) -} +} diff --git a/vulkano/src/buffer/sys.rs b/vulkano/src/buffer/sys.rs index 9eff5376..d7478622 100644 --- a/vulkano/src/buffer/sys.rs +++ b/vulkano/src/buffer/sys.rs @@ -8,15 +8,15 @@ // according to those terms. //! Low level implementation of buffers. -//! +//! //! Wraps directly around Vulkan buffers, with the exceptions of a few safety checks. -//! +//! //! The `UnsafeBuffer` type is the lowest-level buffer object provided by this library. It is used //! internally by the higher-level buffer types. You are strongly encouraged to have excellent //! knowledge of the Vulkan specs if you want to use an `UnsafeBuffer`. -//! +//! //! Here is what you must take care of when you use an `UnsafeBuffer`: -//! +//! //! - Synchronization, ie. avoid reading and writing simultaneously to the same buffer. //! - Memory aliasing considerations. If you use the same memory to back multiple resources, you //! must ensure that they are not used together and must enable some additional flags. @@ -24,12 +24,12 @@ //! sparse binding. //! - Type safety. +use smallvec::SmallVec; use std::error; use std::fmt; use std::mem; use std::ptr; use std::sync::Arc; -use smallvec::SmallVec; use buffer::BufferUsage; use buffer::usage::usage_to_bits; @@ -39,10 +39,10 @@ use memory::DeviceMemory; use memory::MemoryRequirements; use sync::Sharing; -use check_errors; use Error; use OomError; use VulkanObject; +use check_errors; use vk; /// Data storage in a GPU-accessible location. @@ -81,10 +81,10 @@ impl UnsafeBuffer { let usage_bits = usage_to_bits(usage); // Checking sparse features. - assert!(sparse.sparse || !sparse.sparse_residency, "Can't enable sparse residency without \ - enabling sparse binding as well"); - assert!(sparse.sparse || !sparse.sparse_aliased, "Can't enable sparse aliasing without \ - enabling sparse binding as well"); + assert!(sparse.sparse || !sparse.sparse_residency, + "Can't enable sparse residency without enabling sparse binding as well"); + assert!(sparse.sparse || !sparse.sparse_aliased, + "Can't enable sparse aliasing without enabling sparse binding as well"); if sparse.sparse && !device.enabled_features().sparse_binding { return Err(BufferCreationError::SparseBindingFeatureNotEnabled); } @@ -113,13 +113,18 @@ impl UnsafeBuffer { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateBuffer(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateBuffer(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; let mem_reqs = { - #[inline] fn align(val: usize, al: usize) -> usize { al * (1 + (val - 1) / al) } + #[inline] + fn align(val: usize, al: usize) -> usize { + al * (1 + (val - 1) / al) + } let mut output: vk::MemoryRequirements = mem::uninitialized(); vk.GetBufferMemoryRequirements(device.internal_object(), buffer, &mut output); @@ -158,20 +163,19 @@ impl UnsafeBuffer { Ok((obj, mem_reqs)) } - pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize) - -> Result<(), OomError> - { + pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize) -> Result<(), OomError> { let vk = self.device.pointers(); // We check for correctness in debug mode. debug_assert!({ - let mut mem_reqs = mem::uninitialized(); - vk.GetBufferMemoryRequirements(self.device.internal_object(), self.buffer, - &mut mem_reqs); - mem_reqs.size <= (memory.size() - offset) as u64 && - (offset as u64 % mem_reqs.alignment) == 0 && - mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0 - }); + let mut mem_reqs = mem::uninitialized(); + vk.GetBufferMemoryRequirements(self.device.internal_object(), + self.buffer, + &mut mem_reqs); + mem_reqs.size <= (memory.size() - offset) as u64 && + (offset as u64 % mem_reqs.alignment) == 0 && + mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0 + }); // Check for alignment correctness. { @@ -187,8 +191,10 @@ impl UnsafeBuffer { } } - try!(check_errors(vk.BindBufferMemory(self.device.internal_object(), self.buffer, - memory.internal_object(), offset as vk::DeviceSize))); + check_errors(vk.BindBufferMemory(self.device.internal_object(), + self.buffer, + memory.internal_object(), + offset as vk::DeviceSize))?; Ok(()) } @@ -303,9 +309,15 @@ impl SparseLevel { #[inline] fn to_flags(&self) -> vk::BufferCreateFlagBits { let mut result = 0; - if self.sparse { result |= vk::BUFFER_CREATE_SPARSE_BINDING_BIT; } - if self.sparse_residency { result |= vk::BUFFER_CREATE_SPARSE_RESIDENCY_BIT; } - if self.sparse_aliased { result |= vk::BUFFER_CREATE_SPARSE_ALIASED_BIT; } + if self.sparse { + result |= vk::BUFFER_CREATE_SPARSE_BINDING_BIT; + } + if self.sparse_residency { + result |= vk::BUFFER_CREATE_SPARSE_RESIDENCY_BIT; + } + if self.sparse_aliased { + result |= vk::BUFFER_CREATE_SPARSE_ALIASED_BIT; + } result } } @@ -344,7 +356,7 @@ impl error::Error for BufferCreationError { fn cause(&self) -> Option<&error::Error> { match *self { BufferCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -369,7 +381,7 @@ impl From for BufferCreationError { match err { err @ Error::OutOfHostMemory => BufferCreationError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => BufferCreationError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -379,9 +391,9 @@ mod tests { use std::iter::Empty; use super::BufferCreationError; + use super::BufferUsage; use super::SparseLevel; use super::UnsafeBuffer; - use super::BufferUsage; use device::Device; use device::DeviceOwned; @@ -391,7 +403,10 @@ mod tests { fn create() { let (device, _) = gfx_dev_and_queue!(); let (buf, reqs) = unsafe { - UnsafeBuffer::new(device.clone(), 128, BufferUsage::all(), Sharing::Exclusive::>, + UnsafeBuffer::new(device.clone(), + 128, + BufferUsage::all(), + Sharing::Exclusive::>, SparseLevel::none()) }.unwrap(); @@ -401,23 +416,39 @@ mod tests { } #[test] - #[should_panic(expected = "Can't enable sparse residency without enabling sparse binding as well")] + #[should_panic(expected = "Can't enable sparse residency without enabling sparse \ + binding as well")] fn panic_wrong_sparse_residency() { let (device, _) = gfx_dev_and_queue!(); - let sparse = SparseLevel { sparse: false, sparse_residency: true, sparse_aliased: false }; + let sparse = SparseLevel { + sparse: false, + sparse_residency: true, + sparse_aliased: false, + }; let _ = unsafe { - UnsafeBuffer::new(device, 128, BufferUsage::all(), Sharing::Exclusive::>, + UnsafeBuffer::new(device, + 128, + BufferUsage::all(), + Sharing::Exclusive::>, sparse) }; } #[test] - #[should_panic(expected = "Can't enable sparse aliasing without enabling sparse binding as well")] + #[should_panic(expected = "Can't enable sparse aliasing without enabling sparse \ + binding as well")] fn panic_wrong_sparse_aliased() { let (device, _) = gfx_dev_and_queue!(); - let sparse = SparseLevel { sparse: false, sparse_residency: false, sparse_aliased: true }; + let sparse = SparseLevel { + sparse: false, + sparse_residency: false, + sparse_aliased: true, + }; let _ = unsafe { - UnsafeBuffer::new(device, 128, BufferUsage::all(), Sharing::Exclusive::>, + UnsafeBuffer::new(device, + 128, + BufferUsage::all(), + Sharing::Exclusive::>, sparse) }; } @@ -425,13 +456,19 @@ mod tests { #[test] fn missing_feature_sparse_binding() { let (device, _) = gfx_dev_and_queue!(); - let sparse = SparseLevel { sparse: true, sparse_residency: false, sparse_aliased: false }; + let sparse = SparseLevel { + sparse: true, + sparse_residency: false, + sparse_aliased: false, + }; unsafe { - match UnsafeBuffer::new(device, 128, BufferUsage::all(), Sharing::Exclusive::>, - sparse) - { + match UnsafeBuffer::new(device, + 128, + BufferUsage::all(), + Sharing::Exclusive::>, + sparse) { Err(BufferCreationError::SparseBindingFeatureNotEnabled) => (), - _ => panic!() + _ => panic!(), } }; } @@ -439,13 +476,19 @@ mod tests { #[test] fn missing_feature_sparse_residency() { let (device, _) = gfx_dev_and_queue!(sparse_binding); - let sparse = SparseLevel { sparse: true, sparse_residency: true, sparse_aliased: false }; + let sparse = SparseLevel { + sparse: true, + sparse_residency: true, + sparse_aliased: false, + }; unsafe { - match UnsafeBuffer::new(device, 128, BufferUsage::all(), Sharing::Exclusive::>, - sparse) - { + match UnsafeBuffer::new(device, + 128, + BufferUsage::all(), + Sharing::Exclusive::>, + sparse) { Err(BufferCreationError::SparseResidencyBufferFeatureNotEnabled) => (), - _ => panic!() + _ => panic!(), } }; } @@ -453,13 +496,19 @@ mod tests { #[test] fn missing_feature_sparse_aliased() { let (device, _) = gfx_dev_and_queue!(sparse_binding); - let sparse = SparseLevel { sparse: true, sparse_residency: false, sparse_aliased: true }; + let sparse = SparseLevel { + sparse: true, + sparse_residency: false, + sparse_aliased: true, + }; unsafe { - match UnsafeBuffer::new(device, 128, BufferUsage::all(), Sharing::Exclusive::>, - sparse) - { + match UnsafeBuffer::new(device, + 128, + BufferUsage::all(), + Sharing::Exclusive::>, + sparse) { Err(BufferCreationError::SparseResidencyAliasedFeatureNotEnabled) => (), - _ => panic!() + _ => panic!(), } }; } @@ -469,7 +518,11 @@ mod tests { let (device, _) = gfx_dev_and_queue!(); unsafe { - let _ = UnsafeBuffer::new(device, 0, BufferUsage::all(), Sharing::Exclusive::>, SparseLevel::none()); + let _ = UnsafeBuffer::new(device, + 0, + BufferUsage::all(), + Sharing::Exclusive::>, + SparseLevel::none()); }; } } diff --git a/vulkano/src/buffer/traits.rs b/vulkano/src/buffer/traits.rs index b222e3f8..c49abafa 100644 --- a/vulkano/src/buffer/traits.rs +++ b/vulkano/src/buffer/traits.rs @@ -39,7 +39,10 @@ pub unsafe trait BufferAccess: DeviceOwned { /// /// This method can only be called for buffers whose type is known to be an array. #[inline] - fn len(&self) -> usize where Self: TypedBufferAccess, Self::Content: Content { + fn len(&self) -> usize + where Self: TypedBufferAccess, + Self::Content: Content + { self.size() / ::indiv_size() } @@ -95,10 +98,9 @@ pub unsafe trait BufferAccess: DeviceOwned { /// /// If this function returns `false`, this means that we are allowed to access the offset/size /// of `self` at the same time as the offset/size of `other` without causing a data race. - fn conflicts_buffer(&self, self_offset: usize, self_size: usize, - other: &BufferAccess, other_offset: usize, other_size: usize) - -> bool - { + fn conflicts_buffer(&self, self_offset: usize, self_size: usize, other: &BufferAccess, + other_offset: usize, other_size: usize) + -> bool { // TODO: should we really provide a default implementation? debug_assert!(self_size <= self.size()); @@ -129,9 +131,11 @@ pub unsafe trait BufferAccess: DeviceOwned { /// of `self` at the same time as the offset/size of `other` without causing a data race. fn conflicts_image(&self, self_offset: usize, self_size: usize, other: &ImageAccess, other_first_layer: u32, other_num_layers: u32, other_first_mipmap: u32, - other_num_mipmaps: u32) -> bool - { - let other_key = other.conflict_key(other_first_layer, other_num_layers, other_first_mipmap, + other_num_mipmaps: u32) + -> bool { + let other_key = other.conflict_key(other_first_layer, + other_num_layers, + other_first_mipmap, other_num_mipmaps); self.conflict_key(self_offset, self_size) == other_key } @@ -161,7 +165,12 @@ pub unsafe trait BufferAccess: DeviceOwned { /// Shortcut for `conflicts_image` that compares the whole buffer to a whole image. #[inline] fn conflicts_image_all(&self, other: &ImageAccess) -> bool { - self.conflicts_image(0, self.size(), other, 0, other.dimensions().array_layers(), 0, + self.conflicts_image(0, + self.size(), + other, + 0, + other.dimensions().array_layers(), + 0, other.mipmap_levels()) } @@ -214,7 +223,10 @@ pub struct BufferInner<'a> { pub offset: usize, } -unsafe impl BufferAccess for T where T: SafeDeref, T::Target: BufferAccess { +unsafe impl BufferAccess for T + where T: SafeDeref, + T::Target: BufferAccess +{ #[inline] fn inner(&self) -> BufferInner { (**self).inner() @@ -226,9 +238,9 @@ unsafe impl BufferAccess for T where T: SafeDeref, T::Target: BufferAccess { } #[inline] - fn conflicts_buffer(&self, self_offset: usize, self_size: usize, - other: &BufferAccess, other_offset: usize, other_size: usize) -> bool - { + fn conflicts_buffer(&self, self_offset: usize, self_size: usize, other: &BufferAccess, + other_offset: usize, other_size: usize) + -> bool { (**self).conflicts_buffer(self_offset, self_size, other, other_offset, other_size) } @@ -259,6 +271,9 @@ pub unsafe trait TypedBufferAccess: BufferAccess { type Content: ?Sized; } -unsafe impl TypedBufferAccess for T where T: SafeDeref, T::Target: TypedBufferAccess { +unsafe impl TypedBufferAccess for T + where T: SafeDeref, + T::Target: TypedBufferAccess +{ type Content = ::Content; } diff --git a/vulkano/src/buffer/usage.rs b/vulkano/src/buffer/usage.rs index 6e897004..39b5a337 100644 --- a/vulkano/src/buffer/usage.rs +++ b/vulkano/src/buffer/usage.rs @@ -67,7 +67,7 @@ impl BufferUsage { pub fn transfer_source() -> BufferUsage { BufferUsage { transfer_source: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -76,7 +76,7 @@ impl BufferUsage { pub fn transfer_dest() -> BufferUsage { BufferUsage { transfer_dest: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -85,7 +85,7 @@ impl BufferUsage { pub fn vertex_buffer() -> BufferUsage { BufferUsage { vertex_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -96,7 +96,7 @@ impl BufferUsage { BufferUsage { vertex_buffer: true, transfer_dest: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -105,7 +105,7 @@ impl BufferUsage { pub fn index_buffer() -> BufferUsage { BufferUsage { index_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -115,7 +115,7 @@ impl BufferUsage { BufferUsage { index_buffer: true, transfer_dest: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -124,7 +124,7 @@ impl BufferUsage { pub fn uniform_buffer() -> BufferUsage { BufferUsage { uniform_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -135,7 +135,7 @@ impl BufferUsage { BufferUsage { uniform_buffer: true, transfer_dest: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -144,7 +144,7 @@ impl BufferUsage { pub fn indirect_buffer() -> BufferUsage { BufferUsage { indirect_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() } } @@ -155,7 +155,7 @@ impl BufferUsage { BufferUsage { indirect_buffer: true, transfer_dest: true, - .. BufferUsage::none() + ..BufferUsage::none() } } } @@ -183,14 +183,32 @@ impl BitOr for BufferUsage { #[inline] pub fn usage_to_bits(usage: BufferUsage) -> vk::BufferUsageFlagBits { let mut result = 0; - if usage.transfer_source { result |= vk::BUFFER_USAGE_TRANSFER_SRC_BIT; } - if usage.transfer_dest { result |= vk::BUFFER_USAGE_TRANSFER_DST_BIT; } - if usage.uniform_texel_buffer { result |= vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; } - if usage.storage_texel_buffer { result |= vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; } - if usage.uniform_buffer { result |= vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT; } - if usage.storage_buffer { result |= vk::BUFFER_USAGE_STORAGE_BUFFER_BIT; } - if usage.index_buffer { result |= vk::BUFFER_USAGE_INDEX_BUFFER_BIT; } - if usage.vertex_buffer { result |= vk::BUFFER_USAGE_VERTEX_BUFFER_BIT; } - if usage.indirect_buffer { result |= vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT; } + if usage.transfer_source { + result |= vk::BUFFER_USAGE_TRANSFER_SRC_BIT; + } + if usage.transfer_dest { + result |= vk::BUFFER_USAGE_TRANSFER_DST_BIT; + } + if usage.uniform_texel_buffer { + result |= vk::BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; + } + if usage.storage_texel_buffer { + result |= vk::BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; + } + if usage.uniform_buffer { + result |= vk::BUFFER_USAGE_UNIFORM_BUFFER_BIT; + } + if usage.storage_buffer { + result |= vk::BUFFER_USAGE_STORAGE_BUFFER_BIT; + } + if usage.index_buffer { + result |= vk::BUFFER_USAGE_INDEX_BUFFER_BIT; + } + if usage.vertex_buffer { + result |= vk::BUFFER_USAGE_VERTEX_BUFFER_BIT; + } + if usage.indirect_buffer { + result |= vk::BUFFER_USAGE_INDIRECT_BUFFER_BIT; + } result } diff --git a/vulkano/src/buffer/view.rs b/vulkano/src/buffer/view.rs index 8a3b9405..4ff9887f 100644 --- a/vulkano/src/buffer/view.rs +++ b/vulkano/src/buffer/view.rs @@ -8,10 +8,10 @@ // according to those terms. //! View of a buffer, in order to use it as a uniform texel buffer or storage texel buffer. -//! +//! //! In order to use a buffer as a uniform texel buffer or a storage texel buffer, you have to //! create a `BufferView`, which indicates which format the data is in. -//! +//! //! In order to create a view from a buffer, the buffer must have been created with either the //! `uniform_texel_buffer` or the `storage_texel_buffer` usage. //! @@ -37,9 +37,9 @@ //! let _view = BufferView::new(buffer, format::R32Uint).unwrap(); //! ``` -use std::marker::PhantomData; use std::error; use std::fmt; +use std::marker::PhantomData; use std::mem; use std::ptr; use std::sync::Arc; @@ -61,40 +61,42 @@ use vk; /// Represents a way for the GPU to interpret buffer data. See the documentation of the /// `view` module. -pub struct BufferView where B: BufferAccess { +pub struct BufferView + where B: BufferAccess +{ view: vk::BufferView, buffer: B, marker: PhantomData, atomic_accesses: bool, } -impl BufferView where B: BufferAccess { +impl BufferView + where B: BufferAccess +{ /// Builds a new buffer view. #[inline] pub fn new(buffer: B, format: F) -> Result, BufferViewCreationError> where B: TypedBufferAccess, F: StrongStorage + 'static { - unsafe { - BufferView::unchecked(buffer, format) - } + unsafe { BufferView::unchecked(buffer, format) } } /// Builds a new buffer view from a `BufferAccess` object. #[inline] #[deprecated = "Use new() instead"] pub fn from_access(buffer: B, format: F) -> Result, BufferViewCreationError> - where B: TypedBufferAccess, F: StrongStorage + 'static + where B: TypedBufferAccess, + F: StrongStorage + 'static { - unsafe { - BufferView::unchecked(buffer, format) - } + unsafe { BufferView::unchecked(buffer, format) } } /// Builds a new buffer view without checking that the format is correct. pub unsafe fn unchecked(org_buffer: B, format: F) -> Result, BufferViewCreationError> - where B: BufferAccess, F: FormatDesc + 'static + where B: BufferAccess, + F: FormatDesc + 'static { let (view, format_props) = { let size = org_buffer.size(); @@ -110,8 +112,14 @@ impl BufferView where B: BufferAccess { } { - let nb = size / format.size().expect("Can't use a compressed format for buffer views"); - let l = device.physical_device().limits().max_texel_buffer_elements(); + let nb = size / + format + .size() + .expect("Can't use a compressed format for buffer views"); + let l = device + .physical_device() + .limits() + .max_texel_buffer_elements(); if nb > l as usize { return Err(BufferViewCreationError::MaxTexelBufferElementsExceeded); } @@ -121,7 +129,8 @@ impl BufferView where B: BufferAccess { let vk_i = device.instance().pointers(); let mut output = mem::uninitialized(); vk_i.GetPhysicalDeviceFormatProperties(device.physical_device().internal_object(), - format as u32, &mut output); + format as u32, + &mut output); output.bufferFeatures }; @@ -140,7 +149,7 @@ impl BufferView where B: BufferAccess { let infos = vk::BufferViewCreateInfo { sType: vk::STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved, + flags: 0, // reserved, buffer: buffer.internal_object(), format: format as u32, offset: offset as u64, @@ -149,18 +158,21 @@ impl BufferView where B: BufferAccess { let vk = device.pointers(); let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateBufferView(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateBufferView(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; (output, format_props) }; Ok(BufferView { - view: view, - buffer: org_buffer, - marker: PhantomData, - atomic_accesses: (format_props & - vk::FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) != 0, - }) + view: view, + buffer: org_buffer, + marker: PhantomData, + atomic_accesses: (format_props & + vk::FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) != + 0, + }) } /// Returns the buffer associated to this view. @@ -188,7 +200,9 @@ impl BufferView where B: BufferAccess { } } -unsafe impl VulkanObject for BufferView where B: BufferAccess { +unsafe impl VulkanObject for BufferView + where B: BufferAccess +{ type Object = vk::BufferView; #[inline] @@ -206,7 +220,9 @@ unsafe impl DeviceOwned for BufferView } } -impl fmt::Debug for BufferView where B: BufferAccess + fmt::Debug { +impl fmt::Debug for BufferView + where B: BufferAccess + fmt::Debug +{ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt.debug_struct("BufferView") .field("raw", &self.view) @@ -215,12 +231,15 @@ impl fmt::Debug for BufferView where B: BufferAccess + fmt::Debug { } } -impl Drop for BufferView where B: BufferAccess { +impl Drop for BufferView + where B: BufferAccess +{ #[inline] fn drop(&mut self) { unsafe { let vk = self.buffer.inner().buffer.device().pointers(); - vk.DestroyBufferView(self.buffer.inner().buffer.device().internal_object(), self.view, + vk.DestroyBufferView(self.buffer.inner().buffer.device().internal_object(), + self.view, ptr::null()); } } @@ -233,7 +252,9 @@ pub unsafe trait BufferViewRef { fn view(&self) -> &BufferView; } -unsafe impl BufferViewRef for BufferView where B: BufferAccess { +unsafe impl BufferViewRef for BufferView + where B: BufferAccess +{ type BufferAccess = B; type Format = F; @@ -243,7 +264,10 @@ unsafe impl BufferViewRef for BufferView where B: BufferAccess { } } -unsafe impl BufferViewRef for T where T: SafeDeref>, B: BufferAccess { +unsafe impl BufferViewRef for T + where T: SafeDeref>, + B: BufferAccess +{ type BufferAccess = B; type Format = F; @@ -275,10 +299,10 @@ impl error::Error for BufferViewCreationError { fn description(&self) -> &str { match *self { BufferViewCreationError::OomError(_) => "out of memory when creating buffer view", - BufferViewCreationError::WrongBufferUsage => "the buffer is missing correct usage \ - flags", - BufferViewCreationError::UnsupportedFormat => "the requested format is not supported \ - for this usage", + BufferViewCreationError::WrongBufferUsage => + "the buffer is missing correct usage flags", + BufferViewCreationError::UnsupportedFormat => + "the requested format is not supported for this usage", BufferViewCreationError::MaxTexelBufferElementsExceeded => { "the maximum number of texel elements is exceeded" }, @@ -317,10 +341,10 @@ impl From for BufferViewCreationError { #[cfg(test)] mod tests { - use buffer::BufferView; use buffer::BufferUsage; - use buffer::view::BufferViewCreationError; + use buffer::BufferView; use buffer::immutable::ImmutableBuffer; + use buffer::view::BufferViewCreationError; use format; #[test] @@ -330,11 +354,14 @@ mod tests { let usage = BufferUsage { uniform_texel_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() }; - let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, - Some(queue.family()), queue.clone()).unwrap(); + let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0 .. 128).map(|_| [0; 4]), + usage, + Some(queue.family()), + queue.clone()) + .unwrap(); let view = BufferView::new(buffer, format::R8G8B8A8Unorm).unwrap(); assert!(view.uniform_texel_buffer()); @@ -347,12 +374,14 @@ mod tests { let usage = BufferUsage { storage_texel_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() }; - let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, + let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0 .. 128).map(|_| [0; 4]), + usage, Some(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); let view = BufferView::new(buffer, format::R8G8B8A8Unorm).unwrap(); assert!(view.storage_texel_buffer()); @@ -365,12 +394,14 @@ mod tests { let usage = BufferUsage { storage_texel_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() }; - let (buffer, _) = ImmutableBuffer::<[u32]>::from_iter((0..128).map(|_| 0), usage, + let (buffer, _) = ImmutableBuffer::<[u32]>::from_iter((0 .. 128).map(|_| 0), + usage, Some(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); let view = BufferView::new(buffer, format::R32Uint).unwrap(); assert!(view.storage_texel_buffer()); @@ -382,14 +413,15 @@ mod tests { // `VK_FORMAT_R8G8B8A8_UNORM` guaranteed to be a supported format let (device, queue) = gfx_dev_and_queue!(); - let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), + let (buffer, _) = ImmutableBuffer::<[[u8; 4]]>::from_iter((0 .. 128).map(|_| [0; 4]), BufferUsage::none(), Some(queue.family()), - queue.clone()).unwrap(); + queue.clone()) + .unwrap(); match BufferView::new(buffer, format::R8G8B8A8Unorm) { Err(BufferViewCreationError::WrongBufferUsage) => (), - _ => panic!() + _ => panic!(), } } @@ -400,17 +432,19 @@ mod tests { let usage = BufferUsage { uniform_texel_buffer: true, storage_texel_buffer: true, - .. BufferUsage::none() + ..BufferUsage::none() }; - let (buffer, _) = ImmutableBuffer::<[[f64; 4]]>::from_iter((0..128).map(|_| [0.0; 4]), - usage, Some(queue.family()), - queue.clone()).unwrap(); + let (buffer, _) = ImmutableBuffer::<[[f64; 4]]>::from_iter((0 .. 128).map(|_| [0.0; 4]), + usage, + Some(queue.family()), + queue.clone()) + .unwrap(); // TODO: what if R64G64B64A64Sfloat is supported? match BufferView::new(buffer, format::R64G64B64A64Sfloat) { Err(BufferViewCreationError::UnsupportedFormat) => (), - _ => panic!() + _ => panic!(), } } } diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index 19ae4c30..06fcadaa 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -14,6 +14,7 @@ use std::mem; use std::slice; use std::sync::Arc; +use OomError; use buffer::BufferAccess; use buffer::TypedBufferAccess; use command_buffer::CommandBuffer; @@ -29,8 +30,8 @@ use command_buffer::pool::standard::StandardCommandPoolAlloc; use command_buffer::pool::standard::StandardCommandPoolBuilder; use command_buffer::synced::SyncCommandBuffer; use command_buffer::synced::SyncCommandBufferBuilder; -use command_buffer::synced::SyncCommandBufferBuilderError; use command_buffer::synced::SyncCommandBufferBuilderBindVertexBuffer; +use command_buffer::synced::SyncCommandBufferBuilderError; use command_buffer::sys::Flags; use command_buffer::sys::Kind; use command_buffer::sys::UnsafeCommandBuffer; @@ -43,10 +44,10 @@ use device::Device; use device::DeviceOwned; use device::Queue; use framebuffer::FramebufferAbstract; -use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassAbstract; -use image::ImageLayout; +use framebuffer::RenderPassDescClearValues; use image::ImageAccess; +use image::ImageLayout; use instance::QueueFamily; use pipeline::ComputePipelineAbstract; use pipeline::GraphicsPipelineAbstract; @@ -54,9 +55,8 @@ use pipeline::input_assembly::Index; use pipeline::vertex::VertexSource; use sync::AccessCheckError; use sync::AccessFlagBits; -use sync::PipelineStages; use sync::GpuFuture; -use OomError; +use sync::PipelineStages; /// /// @@ -72,17 +72,16 @@ pub struct AutoCommandBufferBuilder

{ impl AutoCommandBufferBuilder { pub fn new(device: Arc, queue_family: QueueFamily) - -> Result, OomError> - { + -> Result, OomError> { unsafe { let pool = Device::standard_command_pool(&device, queue_family); let inner = SyncCommandBufferBuilder::new(&pool, Kind::primary(), Flags::None); let state_cacher = StateCacher::new(); Ok(AutoCommandBufferBuilder { - inner: inner?, - state_cacher: state_cacher, - }) + inner: inner?, + state_cacher: state_cacher, + }) } } } @@ -94,9 +93,7 @@ impl

AutoCommandBufferBuilder

{ where P: CommandPoolBuilderAlloc { // TODO: error if we're inside a render pass - Ok(AutoCommandBuffer { - inner: self.inner.build()? - }) + Ok(AutoCommandBuffer { inner: self.inner.build()? }) } /// Adds a command that enters a render pass. @@ -107,15 +104,15 @@ impl

AutoCommandBufferBuilder

{ /// /// You must call this before you can add draw commands. #[inline] - pub fn begin_render_pass(mut self, framebuffer: F, secondary: bool, - clear_values: C) + pub fn begin_render_pass(mut self, framebuffer: F, secondary: bool, clear_values: C) -> Result where F: FramebufferAbstract + RenderPassDescClearValues + Send + Sync + 'static { unsafe { let clear_values = framebuffer.convert_clear_values(clear_values); - let clear_values = clear_values.collect::>().into_iter(); // TODO: necessary for Send + Sync ; needs an API rework of convert_clear_values - self.inner.begin_render_pass(framebuffer, secondary, clear_values); + let clear_values = clear_values.collect::>().into_iter(); // TODO: necessary for Send + Sync ; needs an API rework of convert_clear_values + self.inner + .begin_render_pass(framebuffer, secondary, clear_values); Ok(self) } } @@ -125,9 +122,10 @@ impl

AutoCommandBufferBuilder

{ /// This command will copy from the source to the destination. If their size is not equal, then /// the amount of data copied is equal to the smallest of the two. #[inline] - pub fn copy_buffer(mut self, src: S, dest: D) -> Result + pub fn copy_buffer(mut self, src: S, dest: D) + -> Result where S: BufferAccess + Send + Sync + 'static, - D: BufferAccess + Send + Sync + 'static, + D: BufferAccess + Send + Sync + 'static { unsafe { // TODO: check that we're not in a render pass @@ -143,19 +141,19 @@ impl

AutoCommandBufferBuilder

{ pub fn copy_buffer_to_image(mut self, src: S, dest: D) -> Result where S: BufferAccess + Send + Sync + 'static, - D: ImageAccess + Send + Sync + 'static, + D: ImageAccess + Send + Sync + 'static { let dims = dest.dimensions().width_height_depth(); self.copy_buffer_to_image_dimensions(src, dest, [0, 0, 0], dims, 0, 1, 0) } /// Adds a command that copies from a buffer to an image. - pub fn copy_buffer_to_image_dimensions(mut self, src: S, dest: D, offset: [u32; 3], - size: [u32; 3], first_layer: u32, num_layers: u32, - mipmap: u32) - -> Result + pub fn copy_buffer_to_image_dimensions( + mut self, src: S, dest: D, offset: [u32; 3], size: [u32; 3], first_layer: u32, + num_layers: u32, mipmap: u32) + -> Result where S: BufferAccess + Send + Sync + 'static, - D: ImageAccess + Send + Sync + 'static, + D: ImageAccess + Send + Sync + 'static { unsafe { // TODO: check that we're not in a render pass @@ -167,7 +165,11 @@ impl

AutoCommandBufferBuilder

{ buffer_row_length: 0, buffer_image_height: 0, image_aspect: if dest.has_color() { - UnsafeCommandBufferBuilderImageAspect { color: true, depth: false, stencil: false } + UnsafeCommandBufferBuilderImageAspect { + color: true, + depth: false, + stencil: false, + } } else { unimplemented!() }, @@ -188,13 +190,15 @@ impl

AutoCommandBufferBuilder

{ #[inline] pub fn dispatch(mut self, dimensions: [u32; 3], pipeline: Cp, sets: S, constants: Pc) -> Result - where Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone - S: DescriptorSetsCollection, + where Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone + S: DescriptorSetsCollection { unsafe { // TODO: missing checks - if let StateCacherOutcome::NeedChange = self.state_cacher.bind_compute_pipeline(&pipeline) { + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_compute_pipeline(&pipeline) + { self.inner.bind_pipeline_compute(pipeline.clone()); } @@ -208,43 +212,50 @@ impl

AutoCommandBufferBuilder

{ #[inline] pub fn draw(mut self, pipeline: Gp, dynamic: DynamicState, vertices: V, sets: S, - constants: Pc) -> Result - where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone - S: DescriptorSetsCollection, + constants: Pc) + -> Result + where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone + S: DescriptorSetsCollection { unsafe { // TODO: missing checks - if let StateCacherOutcome::NeedChange = self.state_cacher.bind_graphics_pipeline(&pipeline) { + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_graphics_pipeline(&pipeline) + { self.inner.bind_pipeline_graphics(pipeline.clone()); } push_constants(&mut self.inner, pipeline.clone(), constants); set_state(&mut self.inner, dynamic); descriptor_sets(&mut self.inner, true, pipeline.clone(), sets); - let (vertex_count, instance_count) = vertex_buffers(&mut self.inner, &pipeline, - vertices); + let (vertex_count, instance_count) = + vertex_buffers(&mut self.inner, &pipeline, vertices); - self.inner.draw(vertex_count as u32, instance_count as u32, 0, 0); + self.inner + .draw(vertex_count as u32, instance_count as u32, 0, 0); Ok(self) } } #[inline] - pub fn draw_indexed(mut self, pipeline: Gp, dynamic: DynamicState, - vertices: V, index_buffer: Ib, sets: S, - constants: Pc) -> Result - where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone + pub fn draw_indexed( + mut self, pipeline: Gp, dynamic: DynamicState, vertices: V, index_buffer: Ib, sets: S, + constants: Pc) + -> Result + where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone S: DescriptorSetsCollection, Ib: BufferAccess + TypedBufferAccess + Send + Sync + 'static, - I: Index + 'static, + I: Index + 'static { unsafe { // TODO: missing checks let index_count = index_buffer.len(); - if let StateCacherOutcome::NeedChange = self.state_cacher.bind_graphics_pipeline(&pipeline) { + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_graphics_pipeline(&pipeline) + { self.inner.bind_pipeline_graphics(pipeline.clone()); } @@ -262,18 +273,24 @@ impl

AutoCommandBufferBuilder

{ #[inline] pub fn draw_indirect(mut self, pipeline: Gp, dynamic: DynamicState, - vertices: V, indirect_buffer: Ib, sets: S, - constants: Pc) -> Result - where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone + vertices: V, indirect_buffer: Ib, sets: S, constants: Pc) + -> Result + where Gp: GraphicsPipelineAbstract + VertexSource + Send + Sync + 'static + Clone, // TODO: meh for Clone S: DescriptorSetsCollection, - Ib: BufferAccess + TypedBufferAccess + Send + Sync + 'static, + Ib: BufferAccess + + TypedBufferAccess + + Send + + Sync + + 'static { unsafe { // TODO: missing checks let draw_count = indirect_buffer.len() as u32; - if let StateCacherOutcome::NeedChange = self.state_cacher.bind_graphics_pipeline(&pipeline) { + if let StateCacherOutcome::NeedChange = + self.state_cacher.bind_graphics_pipeline(&pipeline) + { self.inner.bind_pipeline_graphics(pipeline.clone()); } @@ -282,7 +299,8 @@ impl

AutoCommandBufferBuilder

{ descriptor_sets(&mut self.inner, true, pipeline.clone(), sets); vertex_buffers(&mut self.inner, &pipeline, vertices); - self.inner.draw_indirect(indirect_buffer, draw_count, + self.inner.draw_indirect(indirect_buffer, + draw_count, mem::size_of::() as u32); Ok(self) } @@ -312,8 +330,9 @@ impl

AutoCommandBufferBuilder

{ /// > this function only for zeroing the content of a buffer by passing `0` for the data. // TODO: not safe because of signalling NaNs #[inline] - pub fn fill_buffer(mut self, buffer: B, data: u32) -> Result - where B: BufferAccess + Send + Sync + 'static, + pub fn fill_buffer(mut self, buffer: B, data: u32) + -> Result + where B: BufferAccess + Send + Sync + 'static { unsafe { // TODO: check that we're not in a render pass @@ -326,8 +345,7 @@ impl

AutoCommandBufferBuilder

{ /// Adds a command that jumps to the next subpass of the current render pass. #[inline] pub fn next_subpass(mut self, secondary: bool) - -> Result - { + -> Result { unsafe { // TODO: check self.inner.next_subpass(secondary); @@ -353,7 +371,7 @@ impl

AutoCommandBufferBuilder

{ if buffer.size() > size_of_data { self.inner.update_buffer(buffer, data); } else { - unimplemented!() // TODO: + unimplemented!() // TODO: //self.inner.update_buffer(buffer.slice(0 .. size_of_data), data); } @@ -377,18 +395,20 @@ unsafe fn push_constants(dest: &mut SyncCommandBufferBuilder

, pipe for num_range in 0 .. pipeline.num_push_constants_ranges() { let range = match pipeline.push_constants_range(num_range) { Some(r) => r, - None => continue + None => continue, }; debug_assert_eq!(range.offset % 4, 0); debug_assert_eq!(range.size % 4, 0); let data = slice::from_raw_parts((&push_constants as *const Pc as *const u8) - .offset(range.offset as isize), + .offset(range.offset as isize), range.size as usize); - dest.push_constants::<_, [u8]>(pipeline.clone(), range.stages, - range.offset as u32, range.size as u32, + dest.push_constants::<_, [u8]>(pipeline.clone(), + range.stages, + range.offset as u32, + range.size as u32, data); } } @@ -400,18 +420,19 @@ unsafe fn set_state

(dest: &mut SyncCommandBufferBuilder

, dynamic: DynamicS } if let Some(ref viewports) = dynamic.viewports { - dest.set_viewport(0, viewports.iter().cloned().collect::>().into_iter()); // TODO: don't collect + dest.set_viewport(0, viewports.iter().cloned().collect::>().into_iter()); // TODO: don't collect } if let Some(ref scissors) = dynamic.scissors { - dest.set_scissor(0, scissors.iter().cloned().collect::>().into_iter()); // TODO: don't collect + dest.set_scissor(0, scissors.iter().cloned().collect::>().into_iter()); // TODO: don't collect } } // Shortcut function to bind vertex buffers. unsafe fn vertex_buffers(dest: &mut SyncCommandBufferBuilder

, pipeline: &Gp, - vertices: V) -> (u32, u32) - where Gp: VertexSource, + vertices: V) + -> (u32, u32) + where Gp: VertexSource { let (vertex_buffers, vertex_count, instance_count) = pipeline.decode(vertices); @@ -451,22 +472,24 @@ unsafe impl

CommandBuffer for AutoCommandBuffer

{ } #[inline] - fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> { + fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) + -> Result<(), CommandBufferExecError> { self.inner.prepare_submit(future, queue) } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { self.inner.check_buffer_access(buffer, exclusive, queue) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - self.inner.check_image_access(image, layout, exclusive, queue) + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { + self.inner + .check_image_access(image, layout, exclusive, queue) } } diff --git a/vulkano/src/command_buffer/mod.rs b/vulkano/src/command_buffer/mod.rs index d0c3bf5d..fdf7c264 100644 --- a/vulkano/src/command_buffer/mod.rs +++ b/vulkano/src/command_buffer/mod.rs @@ -28,10 +28,10 @@ //! Using secondary command buffers leads to slightly lower performances on the GPU, but they have //! two advantages on the CPU side: //! -//! - Building a command buffer is a single-threaded operation, but by using secondary command +//! - Building a command buffer is a single-threaded operation, but by using secondary command //! buffers you can build multiple secondary command buffers in multiple threads simultaneously. -//! - Secondary command buffers can be kept alive between frames. When you always repeat the same -//! operations, it might be a good idea to build a secondary command buffer once at +//! - Secondary command buffers can be kept alive between frames. When you always repeat the same +//! operations, it might be a good idea to build a secondary command buffer once at //! initialization and then reuse it afterwards. //! //! # The `AutoCommandBufferBuilder` @@ -73,8 +73,8 @@ //! alternative command pool implementations and use them. See the `pool` module for more //! information. -pub use self::auto::AutoCommandBufferBuilder; pub use self::auto::AutoCommandBuffer; +pub use self::auto::AutoCommandBufferBuilder; pub use self::state_cacher::StateCacher; pub use self::state_cacher::StateCacherOutcome; pub use self::traits::CommandBuffer; @@ -82,8 +82,8 @@ pub use self::traits::CommandBufferBuild; pub use self::traits::CommandBufferExecError; pub use self::traits::CommandBufferExecFuture; -use pipeline::viewport::Viewport; use pipeline::viewport::Scissor; +use pipeline::viewport::Viewport; pub mod pool; pub mod submit; diff --git a/vulkano/src/command_buffer/pool/mod.rs b/vulkano/src/command_buffer/pool/mod.rs index 62182c0d..988a8e3c 100644 --- a/vulkano/src/command_buffer/pool/mod.rs +++ b/vulkano/src/command_buffer/pool/mod.rs @@ -8,24 +8,24 @@ // according to those terms. //! In the Vulkan API, command buffers must be allocated from *command pools*. -//! +//! //! A command pool holds and manages the memory of one or more command buffers. If you destroy a //! command pool, all of its command buffers are automatically destroyed. -//! +//! //! In vulkano, creating a command buffer requires passing an implementation of the `CommandPool` //! trait. By default vulkano will use the `StandardCommandPool` struct, but you can implement //! this trait yourself by wrapping around the `UnsafeCommandPool` type. use instance::QueueFamily; -use device::DeviceOwned; use OomError; +use device::DeviceOwned; pub use self::standard::StandardCommandPool; +pub use self::sys::CommandPoolTrimError; pub use self::sys::UnsafeCommandPool; pub use self::sys::UnsafeCommandPoolAlloc; pub use self::sys::UnsafeCommandPoolAllocIter; -pub use self::sys::CommandPoolTrimError; pub mod standard; mod sys; diff --git a/vulkano/src/command_buffer/pool/standard.rs b/vulkano/src/command_buffer/pool/standard.rs index 4c63e8a9..ef416d35 100644 --- a/vulkano/src/command_buffer/pool/standard.rs +++ b/vulkano/src/command_buffer/pool/standard.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use fnv::FnvHasher; use std::cmp; use std::collections::HashMap; use std::hash::BuildHasherDefault; @@ -14,7 +15,6 @@ use std::marker::PhantomData; use std::sync::Arc; use std::sync::Mutex; use std::sync::Weak; -use fnv::FnvHasher; use command_buffer::pool::CommandPool; use command_buffer::pool::CommandPoolAlloc; @@ -23,16 +23,18 @@ use command_buffer::pool::UnsafeCommandPool; use command_buffer::pool::UnsafeCommandPoolAlloc; use instance::QueueFamily; -use device::Device; -use device::DeviceOwned; use OomError; use VulkanObject; +use device::Device; +use device::DeviceOwned; // Since the stdlib doesn't have a "thread ID" yet, we store a `Box` for each thread and the // value of the pointer will be used as a thread id. thread_local!(static THREAD_ID: Box = Box::new(0)); #[inline] -fn curr_thread_id() -> usize { THREAD_ID.with(|data| &**data as *const u8 as usize) } +fn curr_thread_id() -> usize { + THREAD_ID.with(|data| &**data as *const u8 as usize) +} /// Standard implementation of a command pool. /// @@ -47,12 +49,15 @@ pub struct StandardCommandPool { queue_family: u32, // For each "thread id" (see `THREAD_ID` above), we store thread-specific info. - per_thread: Mutex>, + per_thread: Mutex>, BuildHasherDefault>>, } -unsafe impl Send for StandardCommandPool {} -unsafe impl Sync for StandardCommandPool {} +unsafe impl Send for StandardCommandPool { +} +unsafe impl Sync for StandardCommandPool { +} struct StandardCommandPoolPerThread { // The Vulkan pool of this thread. @@ -83,7 +88,7 @@ impl StandardCommandPool { } unsafe impl CommandPool for Arc { - type Iter = Box>; // TODO: meh for Box + type Iter = Box>; // TODO: meh for Box type Builder = StandardCommandPoolBuilder; type Alloc = StandardCommandPoolAlloc; @@ -98,13 +103,13 @@ unsafe impl CommandPool for Arc { let per_thread = match per_thread { Some(pt) => pt, None => { - let new_pool = try!(UnsafeCommandPool::new(self.device.clone(), self.queue_family(), - false, true)); + let new_pool = + UnsafeCommandPool::new(self.device.clone(), self.queue_family(), false, true)?; let pt = Arc::new(Mutex::new(StandardCommandPoolPerThread { - pool: new_pool, - available_primary_command_buffers: Vec::new(), - available_secondary_command_buffers: Vec::new(), - })); + pool: new_pool, + available_primary_command_buffers: Vec::new(), + available_secondary_command_buffers: Vec::new(), + })); hashmap.insert(curr_thread_id, Arc::downgrade(&pt)); pt @@ -116,39 +121,51 @@ unsafe impl CommandPool for Arc { // Build an iterator to pick from already-existing command buffers. let (num_from_existing, from_existing) = { // Which list of already-existing command buffers we are going to pick CBs from. - let mut existing = if secondary { &mut pt_lock.available_secondary_command_buffers } - else { &mut pt_lock.available_primary_command_buffers }; + let mut existing = if secondary { + &mut pt_lock.available_secondary_command_buffers + } else { + &mut pt_lock.available_primary_command_buffers + }; let num_from_existing = cmp::min(count as usize, existing.len()); - let from_existing = existing.drain(0 .. num_from_existing).collect::>().into_iter(); + let from_existing = existing + .drain(0 .. num_from_existing) + .collect::>() + .into_iter(); (num_from_existing, from_existing) }; // Build an iterator to construct the missing command buffers from the Vulkan pool. let num_new = count as usize - num_from_existing; - debug_assert!(num_new <= count as usize); // Check overflows. - let newly_allocated = try!(pt_lock.pool.alloc_command_buffers(secondary, num_new)); + debug_assert!(num_new <= count as usize); // Check overflows. + let newly_allocated = pt_lock.pool.alloc_command_buffers(secondary, num_new)?; // Returning them as a chain. let device = self.device.clone(); let queue_family_id = self.queue_family; let per_thread = per_thread.clone(); - let final_iter = from_existing.chain(newly_allocated).map(move |cmd| { - StandardCommandPoolBuilder { - cmd: Some(cmd), - pool: per_thread.clone(), - secondary: secondary, - device: device.clone(), - queue_family_id: queue_family_id, - dummy_avoid_send_sync: PhantomData, - } - }).collect::>(); + let final_iter = from_existing + .chain(newly_allocated) + .map(move |cmd| { + StandardCommandPoolBuilder { + cmd: Some(cmd), + pool: per_thread.clone(), + secondary: secondary, + device: device.clone(), + queue_family_id: queue_family_id, + dummy_avoid_send_sync: PhantomData, + } + }) + .collect::>(); Ok(Box::new(final_iter.into_iter())) } #[inline] fn queue_family(&self) -> QueueFamily { - self.device.physical_device().queue_family_by_id(self.queue_family).unwrap() + self.device + .physical_device() + .queue_family_by_id(self.queue_family) + .unwrap() } } @@ -189,7 +206,10 @@ unsafe impl CommandPoolBuilderAlloc for StandardCommandPoolBuilder { #[inline] fn queue_family(&self) -> QueueFamily { - self.device.physical_device().queue_family_by_id(self.queue_family_id).unwrap() + self.device + .physical_device() + .queue_family_by_id(self.queue_family_id) + .unwrap() } } @@ -222,8 +242,10 @@ pub struct StandardCommandPoolAlloc { queue_family_id: u32, } -unsafe impl Send for StandardCommandPoolAlloc {} -unsafe impl Sync for StandardCommandPoolAlloc {} +unsafe impl Send for StandardCommandPoolAlloc { +} +unsafe impl Sync for StandardCommandPoolAlloc { +} unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc { #[inline] @@ -233,7 +255,10 @@ unsafe impl CommandPoolAlloc for StandardCommandPoolAlloc { #[inline] fn queue_family(&self) -> QueueFamily { - self.device.physical_device().queue_family_by_id(self.queue_family_id).unwrap() + self.device + .physical_device() + .queue_family_by_id(self.queue_family_id) + .unwrap() } } @@ -249,9 +274,11 @@ impl Drop for StandardCommandPoolAlloc { let mut pool = self.pool.lock().unwrap(); if self.secondary { - pool.available_secondary_command_buffers.push(self.cmd.take().unwrap()); + pool.available_secondary_command_buffers + .push(self.cmd.take().unwrap()); } else { - pool.available_primary_command_buffers.push(self.cmd.take().unwrap()); + pool.available_primary_command_buffers + .push(self.cmd.take().unwrap()); } } } diff --git a/vulkano/src/command_buffer/pool/sys.rs b/vulkano/src/command_buffer/pool/sys.rs index 270de998..1c6aa8d9 100644 --- a/vulkano/src/command_buffer/pool/sys.rs +++ b/vulkano/src/command_buffer/pool/sys.rs @@ -7,23 +7,23 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; +use std::error; +use std::fmt; use std::marker::PhantomData; use std::mem; use std::ptr; -use std::error; -use std::fmt; use std::sync::Arc; use std::vec::IntoIter as VecIntoIter; -use smallvec::SmallVec; use instance::QueueFamily; -use device::Device; -use device::DeviceOwned; +use Error; use OomError; use VulkanObject; -use Error; use check_errors; +use device::Device; +use device::DeviceOwned; use vk; /// Low-level implementation of a command pool. @@ -46,7 +46,8 @@ pub struct UnsafeCommandPool { dummy_avoid_sync: PhantomData<*const u8>, } -unsafe impl Send for UnsafeCommandPool {} +unsafe impl Send for UnsafeCommandPool { +} impl UnsafeCommandPool { /// Creates a new pool. @@ -62,9 +63,8 @@ impl UnsafeCommandPool { /// /// - Panics if the queue family doesn't belong to the same physical device as `device`. /// - pub fn new(device: Arc, queue_family: QueueFamily, transient: bool, - reset_cb: bool) -> Result - { + pub fn new(device: Arc, queue_family: QueueFamily, transient: bool, reset_cb: bool) + -> Result { assert_eq!(device.physical_device().internal_object(), queue_family.physical_device().internal_object(), "Device doesn't match physical device when creating a command pool"); @@ -72,9 +72,16 @@ impl UnsafeCommandPool { let vk = device.pointers(); let flags = { - let flag1 = if transient { vk::COMMAND_POOL_CREATE_TRANSIENT_BIT } else { 0 }; - let flag2 = if reset_cb { vk::COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT } - else { 0 }; + let flag1 = if transient { + vk::COMMAND_POOL_CREATE_TRANSIENT_BIT + } else { + 0 + }; + let flag2 = if reset_cb { + vk::COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + } else { + 0 + }; flag1 | flag2 }; @@ -87,17 +94,19 @@ impl UnsafeCommandPool { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateCommandPool(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateCommandPool(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(UnsafeCommandPool { - pool: pool, - device: device.clone(), - queue_family_index: queue_family.id(), - dummy_avoid_sync: PhantomData, - }) + pool: pool, + device: device.clone(), + queue_family_index: queue_family.id(), + dummy_avoid_sync: PhantomData, + }) } /// Resets the pool, which resets all the command buffers that were allocated from it. @@ -110,11 +119,14 @@ impl UnsafeCommandPool { /// The command buffers allocated from this pool jump to the initial state. /// pub unsafe fn reset(&self, release_resources: bool) -> Result<(), OomError> { - let flags = if release_resources { vk::COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT } - else { 0 }; + let flags = if release_resources { + vk::COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT + } else { + 0 + }; let vk = self.device.pointers(); - try!(check_errors(vk.ResetCommandPool(self.device.internal_object(), self.pool, flags))); + check_errors(vk.ResetCommandPool(self.device.internal_object(), self.pool, flags))?; Ok(()) } @@ -134,7 +146,9 @@ impl UnsafeCommandPool { } let vk = self.device.pointers(); - vk.TrimCommandPoolKHR(self.device.internal_object(), self.pool, 0 /* reserved */); + vk.TrimCommandPoolKHR(self.device.internal_object(), + self.pool, + 0 /* reserved */); Ok(()) } } @@ -144,34 +158,33 @@ impl UnsafeCommandPool { /// If `secondary` is true, allocates secondary command buffers. Otherwise, allocates primary /// command buffers. pub fn alloc_command_buffers(&self, secondary: bool, count: usize) - -> Result - { + -> Result { if count == 0 { - return Ok(UnsafeCommandPoolAllocIter { - list: None - }); + return Ok(UnsafeCommandPoolAllocIter { list: None }); } let infos = vk::CommandBufferAllocateInfo { sType: vk::STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, pNext: ptr::null(), commandPool: self.pool, - level: if secondary { vk::COMMAND_BUFFER_LEVEL_SECONDARY } - else { vk::COMMAND_BUFFER_LEVEL_PRIMARY }, + level: if secondary { + vk::COMMAND_BUFFER_LEVEL_SECONDARY + } else { + vk::COMMAND_BUFFER_LEVEL_PRIMARY + }, commandBufferCount: count as u32, }; unsafe { let vk = self.device.pointers(); let mut out = Vec::with_capacity(count); - try!(check_errors(vk.AllocateCommandBuffers(self.device.internal_object(), &infos, - out.as_mut_ptr()))); + check_errors(vk.AllocateCommandBuffers(self.device.internal_object(), + &infos, + out.as_mut_ptr()))?; out.set_len(count); - Ok(UnsafeCommandPoolAllocIter { - list: Some(out.into_iter()) - }) + Ok(UnsafeCommandPoolAllocIter { list: Some(out.into_iter()) }) } } @@ -186,14 +199,19 @@ impl UnsafeCommandPool { { let command_buffers: SmallVec<[_; 4]> = command_buffers.map(|cb| cb.0).collect(); let vk = self.device.pointers(); - vk.FreeCommandBuffers(self.device.internal_object(), self.pool, - command_buffers.len() as u32, command_buffers.as_ptr()) + vk.FreeCommandBuffers(self.device.internal_object(), + self.pool, + command_buffers.len() as u32, + command_buffers.as_ptr()) } /// Returns the queue family on which command buffers of this pool can be executed. #[inline] pub fn queue_family(&self) -> QueueFamily { - self.device.physical_device().queue_family_by_id(self.queue_family_index).unwrap() + self.device + .physical_device() + .queue_family_by_id(self.queue_family_index) + .unwrap() } } @@ -238,7 +256,7 @@ unsafe impl VulkanObject for UnsafeCommandPoolAlloc { /// Iterator for newly-allocated command buffers. #[derive(Debug)] pub struct UnsafeCommandPoolAllocIter { - list: Option> + list: Option>, } impl Iterator for UnsafeCommandPoolAllocIter { @@ -246,16 +264,23 @@ impl Iterator for UnsafeCommandPoolAllocIter { #[inline] fn next(&mut self) -> Option { - self.list.as_mut().and_then(|i| i.next()).map(|cb| UnsafeCommandPoolAlloc(cb)) + self.list + .as_mut() + .and_then(|i| i.next()) + .map(|cb| UnsafeCommandPoolAlloc(cb)) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.list.as_ref().map(|i| i.size_hint()).unwrap_or((0, Some(0))) + self.list + .as_ref() + .map(|i| i.size_hint()) + .unwrap_or((0, Some(0))) } } -impl ExactSizeIterator for UnsafeCommandPoolAllocIter {} +impl ExactSizeIterator for UnsafeCommandPoolAllocIter { +} /// Error that can happen when trimming command pools. #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -268,8 +293,8 @@ impl error::Error for CommandPoolTrimError { #[inline] fn description(&self) -> &str { match *self { - CommandPoolTrimError::Maintenance1ExtensionNotEnabled => "the `KHR_maintenance1` \ - extension was not enabled", + CommandPoolTrimError::Maintenance1ExtensionNotEnabled => + "the `KHR_maintenance1` extension was not enabled", } } } @@ -290,8 +315,8 @@ impl From for CommandPoolTrimError { #[cfg(test)] mod tests { - use command_buffer::pool::UnsafeCommandPool; use command_buffer::pool::CommandPoolTrimError; + use command_buffer::pool::UnsafeCommandPool; #[test] fn basic_create() { @@ -321,7 +346,7 @@ mod tests { match pool.trim() { Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) => (), - _ => panic!() + _ => panic!(), } } diff --git a/vulkano/src/command_buffer/state_cacher.rs b/vulkano/src/command_buffer/state_cacher.rs index ae153fa6..6bb0a5db 100644 --- a/vulkano/src/command_buffer/state_cacher.rs +++ b/vulkano/src/command_buffer/state_cacher.rs @@ -7,10 +7,10 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use VulkanObject; use command_buffer::DynamicState; use pipeline::ComputePipelineAbstract; use pipeline::GraphicsPipelineAbstract; -use VulkanObject; use vk; /// Keep track of the state of a command buffer builder, so that you don't need to bind objects diff --git a/vulkano/src/command_buffer/submit/bind_sparse.rs b/vulkano/src/command_buffer/submit/bind_sparse.rs index e5b82fe9..260d1aad 100644 --- a/vulkano/src/command_buffer/submit/bind_sparse.rs +++ b/vulkano/src/command_buffer/submit/bind_sparse.rs @@ -7,11 +7,11 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::marker::PhantomData; use std::ptr; -use smallvec::SmallVec; use buffer::sys::UnsafeBuffer; use device::Queue; @@ -20,12 +20,12 @@ use memory::DeviceMemory; use sync::Fence; use sync::Semaphore; -use check_errors; -use vk; use Error; use OomError; -use VulkanObject; use SynchronizedVulkanObject; +use VulkanObject; +use check_errors; +use vk; // TODO: correctly implement Debug on all the structs of this module @@ -127,8 +127,7 @@ impl<'a> SubmitBindSparseBuilder<'a> { /// error. #[inline] pub fn merge(&mut self, other: SubmitBindSparseBuilder<'a>) - -> Result<(), SubmitBindSparseBuilder<'a>> - { + -> Result<(), SubmitBindSparseBuilder<'a>> { if self.fence != 0 && other.fence != 0 { return Err(other); } @@ -147,39 +146,42 @@ impl<'a> SubmitBindSparseBuilder<'a> { // We start by storing all the `VkSparseBufferMemoryBindInfo`s of the whole command // in the same collection. - let buffer_binds_storage: SmallVec<[_; 4]> = self.infos.iter() + let buffer_binds_storage: SmallVec<[_; 4]> = self.infos + .iter() .flat_map(|infos| infos.buffer_binds.iter()) .map(|buf_bind| { - vk::SparseBufferMemoryBindInfo { - buffer: buf_bind.buffer, - bindCount: buf_bind.binds.len() as u32, - pBinds: buf_bind.binds.as_ptr(), - } - }) + vk::SparseBufferMemoryBindInfo { + buffer: buf_bind.buffer, + bindCount: buf_bind.binds.len() as u32, + pBinds: buf_bind.binds.as_ptr(), + } + }) .collect(); // Same for all the `VkSparseImageOpaqueMemoryBindInfo`s. - let image_opaque_binds_storage: SmallVec<[_; 4]> = self.infos.iter() + let image_opaque_binds_storage: SmallVec<[_; 4]> = self.infos + .iter() .flat_map(|infos| infos.image_opaque_binds.iter()) .map(|img_bind| { - vk::SparseImageOpaqueMemoryBindInfo { - image: img_bind.image, - bindCount: img_bind.binds.len() as u32, - pBinds: img_bind.binds.as_ptr(), - } - }) + vk::SparseImageOpaqueMemoryBindInfo { + image: img_bind.image, + bindCount: img_bind.binds.len() as u32, + pBinds: img_bind.binds.as_ptr(), + } + }) .collect(); // And finally the `VkSparseImageMemoryBindInfo`s. - let image_binds_storage: SmallVec<[_; 4]> = self.infos.iter() + let image_binds_storage: SmallVec<[_; 4]> = self.infos + .iter() .flat_map(|infos| infos.image_binds.iter()) .map(|img_bind| { - vk::SparseImageMemoryBindInfo { - image: img_bind.image, - bindCount: img_bind.binds.len() as u32, - pBinds: img_bind.binds.as_ptr(), - } - }) + vk::SparseImageMemoryBindInfo { + image: img_bind.image, + bindCount: img_bind.binds.len() as u32, + pBinds: img_bind.binds.as_ptr(), + } + }) .collect(); // Now building the collection of `VkBindSparseInfo`s. @@ -231,14 +233,17 @@ impl<'a> SubmitBindSparseBuilder<'a> { // If these assertions fail, then there's something wrong in the code above. debug_assert_eq!(next_buffer_bind as usize, buffer_binds_storage.len()); - debug_assert_eq!(next_image_opaque_bind as usize, image_opaque_binds_storage.len()); + debug_assert_eq!(next_image_opaque_bind as usize, + image_opaque_binds_storage.len()); debug_assert_eq!(next_image_bind as usize, image_binds_storage.len()); bs_infos }; // Finally executing the command. - check_errors(vk.QueueBindSparse(*queue, bs_infos.len() as u32, bs_infos.as_ptr(), + check_errors(vk.QueueBindSparse(*queue, + bs_infos.len() as u32, + bs_infos.as_ptr(), self.fence))?; Ok(()) } @@ -359,25 +364,24 @@ impl<'a> SubmitBindSparseBufferBindBuilder<'a> { } pub unsafe fn add_bind(&mut self, offset: usize, size: usize, memory: &DeviceMemory, - memory_offset: usize) - { + memory_offset: usize) { self.binds.push(vk::SparseMemoryBind { - resourceOffset: offset as vk::DeviceSize, - size: size as vk::DeviceSize, - memory: memory.internal_object(), - memoryOffset: memory_offset as vk::DeviceSize, - flags: 0, // Flags are only relevant for images. - }); + resourceOffset: offset as vk::DeviceSize, + size: size as vk::DeviceSize, + memory: memory.internal_object(), + memoryOffset: memory_offset as vk::DeviceSize, + flags: 0, // Flags are only relevant for images. + }); } pub unsafe fn add_unbind(&mut self, offset: usize, size: usize) { self.binds.push(vk::SparseMemoryBind { - resourceOffset: offset as vk::DeviceSize, - size: size as vk::DeviceSize, - memory: 0, - memoryOffset: 0, - flags: 0, - }); + resourceOffset: offset as vk::DeviceSize, + size: size as vk::DeviceSize, + memory: 0, + memoryOffset: 0, + flags: 0, + }); } } @@ -401,29 +405,28 @@ impl<'a> SubmitBindSparseImageOpaqueBindBuilder<'a> { } pub unsafe fn add_bind(&mut self, offset: usize, size: usize, memory: &DeviceMemory, - memory_offset: usize, bind_metadata: bool) - { + memory_offset: usize, bind_metadata: bool) { self.binds.push(vk::SparseMemoryBind { - resourceOffset: offset as vk::DeviceSize, - size: size as vk::DeviceSize, - memory: memory.internal_object(), - memoryOffset: memory_offset as vk::DeviceSize, - flags: if bind_metadata { - vk::SPARSE_MEMORY_BIND_METADATA_BIT - } else { - 0 - }, - }); + resourceOffset: offset as vk::DeviceSize, + size: size as vk::DeviceSize, + memory: memory.internal_object(), + memoryOffset: memory_offset as vk::DeviceSize, + flags: if bind_metadata { + vk::SPARSE_MEMORY_BIND_METADATA_BIT + } else { + 0 + }, + }); } pub unsafe fn add_unbind(&mut self, offset: usize, size: usize) { self.binds.push(vk::SparseMemoryBind { - resourceOffset: offset as vk::DeviceSize, - size: size as vk::DeviceSize, - memory: 0, - memoryOffset: 0, - flags: 0, // TODO: is that relevant? - }); + resourceOffset: offset as vk::DeviceSize, + size: size as vk::DeviceSize, + memory: 0, + memoryOffset: 0, + flags: 0, // TODO: is that relevant? + }); } } @@ -473,7 +476,7 @@ impl error::Error for SubmitBindSparseError { fn cause(&self) -> Option<&error::Error> { match *self { SubmitBindSparseError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -492,7 +495,7 @@ impl From for SubmitBindSparseError { err @ Error::OutOfHostMemory => SubmitBindSparseError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => SubmitBindSparseError::OomError(OomError::from(err)), Error::DeviceLost => SubmitBindSparseError::DeviceLost, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } diff --git a/vulkano/src/command_buffer/submit/mod.rs b/vulkano/src/command_buffer/submit/mod.rs index 2b5c8421..7688f76f 100644 --- a/vulkano/src/command_buffer/submit/mod.rs +++ b/vulkano/src/command_buffer/submit/mod.rs @@ -13,12 +13,12 @@ //! module. These structs are low-level and unsafe, and are mostly used to implement other parts //! of vulkano, so you are encouraged to not use them directly. -pub use self::bind_sparse::SubmitBindSparseBuilder; pub use self::bind_sparse::SubmitBindSparseBatchBuilder; pub use self::bind_sparse::SubmitBindSparseBufferBindBuilder; -pub use self::bind_sparse::SubmitBindSparseImageOpaqueBindBuilder; -pub use self::bind_sparse::SubmitBindSparseImageBindBuilder; +pub use self::bind_sparse::SubmitBindSparseBuilder; pub use self::bind_sparse::SubmitBindSparseError; +pub use self::bind_sparse::SubmitBindSparseImageBindBuilder; +pub use self::bind_sparse::SubmitBindSparseImageOpaqueBindBuilder; pub use self::queue_present::SubmitPresentBuilder; pub use self::queue_present::SubmitPresentError; pub use self::queue_submit::SubmitCommandBufferBuilder; diff --git a/vulkano/src/command_buffer/submit/queue_present.rs b/vulkano/src/command_buffer/submit/queue_present.rs index e7ef2376..dbee4639 100644 --- a/vulkano/src/command_buffer/submit/queue_present.rs +++ b/vulkano/src/command_buffer/submit/queue_present.rs @@ -7,23 +7,23 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::marker::PhantomData; use std::mem; use std::ptr; -use smallvec::SmallVec; use device::Queue; use swapchain::Swapchain; use sync::Semaphore; -use check_errors; -use vk; use Error; use OomError; -use VulkanObject; use SynchronizedVulkanObject; +use VulkanObject; +use check_errors; +use vk; /// Prototype for a submission that presents a swapchain on the screen. // TODO: example here @@ -100,7 +100,7 @@ impl<'a> SubmitPresentBuilder<'a> { let vk = queue.device().pointers(); let queue = queue.internal_object_guard(); - let mut results = vec![mem::uninitialized(); self.swapchains.len()]; // TODO: alloca + let mut results = vec![mem::uninitialized(); self.swapchains.len()]; // TODO: alloca let infos = vk::PresentInfoKHR { sType: vk::STRUCTURE_TYPE_PRESENT_INFO_KHR, @@ -113,7 +113,7 @@ impl<'a> SubmitPresentBuilder<'a> { pResults: results.as_mut_ptr(), }; - try!(check_errors(vk.QueuePresentKHR(*queue, &infos))); + check_errors(vk.QueuePresentKHR(*queue, &infos))?; for result in results { // TODO: AMD driver initially didn't write the results ; check that it's been fixed @@ -158,7 +158,7 @@ impl error::Error for SubmitPresentError { fn cause(&self) -> Option<&error::Error> { match *self { SubmitPresentError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -179,7 +179,7 @@ impl From for SubmitPresentError { Error::DeviceLost => SubmitPresentError::DeviceLost, Error::SurfaceLost => SubmitPresentError::SurfaceLost, Error::OutOfDate => SubmitPresentError::OutOfDate, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } diff --git a/vulkano/src/command_buffer/submit/queue_submit.rs b/vulkano/src/command_buffer/submit/queue_submit.rs index 0f7a53df..2c5cbd92 100644 --- a/vulkano/src/command_buffer/submit/queue_submit.rs +++ b/vulkano/src/command_buffer/submit/queue_submit.rs @@ -7,11 +7,11 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::marker::PhantomData; use std::ptr; -use smallvec::SmallVec; use command_buffer::sys::UnsafeCommandBuffer; use device::Queue; @@ -19,12 +19,12 @@ use sync::Fence; use sync::PipelineStages; use sync::Semaphore; -use check_errors; -use vk; use Error; use OomError; -use VulkanObject; use SynchronizedVulkanObject; +use VulkanObject; +use check_errors; +use vk; /// Prototype for a submission that executes command buffers. // TODO: example here @@ -219,7 +219,7 @@ impl<'a> SubmitCommandBufferBuilder<'a> { pSignalSemaphores: self.signal_semaphores.as_ptr(), }; - try!(check_errors(vk.QueueSubmit(*queue, 1, &batch, self.fence))); + check_errors(vk.QueueSubmit(*queue, 1, &batch, self.fence))?; Ok(()) } } @@ -232,10 +232,10 @@ impl<'a> SubmitCommandBufferBuilder<'a> { // TODO: create multiple batches instead pub fn merge(mut self, other: Self) -> Self { assert!(self.fence == 0 || other.fence == 0, - "Can't merge two queue submits that both have a fence"); + "Can't merge two queue submits that both have a fence"); self.wait_semaphores.extend(other.wait_semaphores); - self.dest_stages.extend(other.dest_stages); // TODO: meh? will be solved if we submit multiple batches + self.dest_stages.extend(other.dest_stages); // TODO: meh? will be solved if we submit multiple batches self.signal_semaphores.extend(other.signal_semaphores); self.command_buffers.extend(other.command_buffers); @@ -271,7 +271,7 @@ impl error::Error for SubmitCommandBufferError { fn cause(&self) -> Option<&error::Error> { match *self { SubmitCommandBufferError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -288,17 +288,18 @@ impl From for SubmitCommandBufferError { fn from(err: Error) -> SubmitCommandBufferError { match err { err @ Error::OutOfHostMemory => SubmitCommandBufferError::OomError(OomError::from(err)), - err @ Error::OutOfDeviceMemory => SubmitCommandBufferError::OomError(OomError::from(err)), + err @ Error::OutOfDeviceMemory => + SubmitCommandBufferError::OomError(OomError::from(err)), Error::DeviceLost => SubmitCommandBufferError::DeviceLost, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } #[cfg(test)] mod tests { - use std::time::Duration; use super::*; + use std::time::Duration; use sync::Fence; #[test] diff --git a/vulkano/src/command_buffer/submit/semaphores_wait.rs b/vulkano/src/command_buffer/submit/semaphores_wait.rs index 74d4fc00..8b1a02b6 100644 --- a/vulkano/src/command_buffer/submit/semaphores_wait.rs +++ b/vulkano/src/command_buffer/submit/semaphores_wait.rs @@ -27,9 +27,7 @@ impl<'a> SubmitSemaphoresWaitBuilder<'a> { /// Builds a new empty `SubmitSemaphoresWaitBuilder`. #[inline] pub fn new() -> SubmitSemaphoresWaitBuilder<'a> { - SubmitSemaphoresWaitBuilder { - semaphores: SmallVec::new(), - } + SubmitSemaphoresWaitBuilder { semaphores: SmallVec::new() } } /// Adds an operation that waits on a semaphore. @@ -53,11 +51,12 @@ impl<'a> Into> for SubmitSemaphoresWaitBuilder<'a unsafe { let mut builder = SubmitCommandBufferBuilder::new(); for sem in self.semaphores.drain() { - builder.add_wait_semaphore(sem, PipelineStages { - // TODO: correct stages ; hard - all_commands: true, - .. PipelineStages::none() - }); + builder.add_wait_semaphore(sem, + PipelineStages { + // TODO: correct stages ; hard + all_commands: true, + ..PipelineStages::none() + }); } builder } diff --git a/vulkano/src/command_buffer/synced.rs b/vulkano/src/command_buffer/synced.rs index 80962dc8..3fec93f8 100644 --- a/vulkano/src/command_buffer/synced.rs +++ b/vulkano/src/command_buffer/synced.rs @@ -7,6 +7,8 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use fnv::FnvHashMap; +use smallvec::SmallVec; use std::collections::hash_map::Entry; use std::error; use std::fmt; @@ -15,9 +17,8 @@ use std::mem; use std::ptr; use std::sync::Arc; use std::sync::Mutex; -use fnv::FnvHashMap; -use smallvec::SmallVec; +use OomError; use buffer::BufferAccess; use command_buffer::CommandBuffer; use command_buffer::CommandBufferExecError; @@ -31,18 +32,18 @@ use command_buffer::sys::UnsafeCommandBufferBuilder; use command_buffer::sys::UnsafeCommandBufferBuilderBindVertexBuffer; use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy; use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier; -use descriptor::descriptor_set::DescriptorSet; use descriptor::descriptor::ShaderStages; +use descriptor::descriptor_set::DescriptorSet; use descriptor::pipeline_layout::PipelineLayoutAbstract; -use format::ClearValue; -use framebuffer::FramebufferAbstract; -use framebuffer::RenderPassAbstract; -use image::ImageLayout; -use image::ImageAccess; -use image::ImageViewAccess; use device::Device; use device::DeviceOwned; use device::Queue; +use format::ClearValue; +use framebuffer::FramebufferAbstract; +use framebuffer::RenderPassAbstract; +use image::ImageAccess; +use image::ImageLayout; +use image::ImageViewAccess; use pipeline::ComputePipelineAbstract; use pipeline::GraphicsPipelineAbstract; use pipeline::input_assembly::IndexType; @@ -52,9 +53,8 @@ use sync::AccessCheckError; use sync::AccessError; use sync::AccessFlagBits; use sync::Event; -use sync::PipelineStages; use sync::GpuFuture; -use OomError; +use sync::PipelineStages; /// Wrapper around `UnsafeCommandBufferBuilder` that handles synchronization for you. /// @@ -142,9 +142,13 @@ trait Command

{ fn into_final_command(self: Box) -> Box; // Gives access to the `num`th buffer used by the command. - fn buffer(&self, num: usize) -> &BufferAccess { panic!() } + fn buffer(&self, num: usize) -> &BufferAccess { + panic!() + } // Gives access to the `num`th image used by the command. - fn image(&self, num: usize) -> &ImageAccess { panic!() } + fn image(&self, num: usize) -> &ImageAccess { + panic!() + } } // Key that identifies a resource. Implements `PartialEq`, `Eq` and `Hash` so that two resources @@ -173,8 +177,7 @@ impl

BuilderKey

{ // Turns this key used by the builder into a key used by the final command buffer. // Called when the command buffer is being built. fn into_cb_key(self, final_commands: Arc>>>) - -> CbKey<'static> - { + -> CbKey<'static> { CbKey::Command { commands: final_commands, command_id: self.command_id, @@ -322,27 +325,25 @@ impl

SyncCommandBufferBuilder

{ /// any existing resource usage. #[inline] pub unsafe fn from_unsafe_cmd(cmd: UnsafeCommandBufferBuilder

) - -> SyncCommandBufferBuilder

- { + -> SyncCommandBufferBuilder

{ SyncCommandBufferBuilder { inner: cmd, resources: FnvHashMap::default(), pending_barrier: UnsafeCommandBufferBuilderPipelineBarrier::new(), commands: Arc::new(Mutex::new(Commands { - first_unflushed: 0, - commands: Vec::new(), - })), + first_unflushed: 0, + commands: Vec::new(), + })), } } // After a command is added to the list of pending commands, this function must be called for // each resource used by the command that has just been added. // The function will take care of handling the pipeline barrier or flushing. - fn prev_cmd_resource(&mut self, resource_ty: KeyTy, resource_index: usize, - exclusive: bool, stages: PipelineStages, access: AccessFlagBits, + fn prev_cmd_resource(&mut self, resource_ty: KeyTy, resource_index: usize, exclusive: bool, + stages: PipelineStages, access: AccessFlagBits, start_layout: ImageLayout, end_layout: ImageLayout) - -> Result<(), SyncCommandBufferBuilderError> - { + -> Result<(), SyncCommandBufferBuilderError> { debug_assert!(exclusive || start_layout == end_layout); debug_assert!(access.is_compatible_with(&stages)); debug_assert!(resource_ty != KeyTy::Image || end_layout != ImageLayout::Undefined); @@ -406,9 +407,15 @@ impl

SyncCommandBufferBuilder

{ .buffer(resource_index); let b = &mut self.pending_barrier; - b.add_buffer_memory_barrier(buf, entry.stages, entry.access, - stages, access, true, None, - 0, buf.size()); + b.add_buffer_memory_barrier(buf, + entry.stages, + entry.access, + stages, + access, + true, + None, + 0, + buf.size()); }, KeyTy::Image => { @@ -416,11 +423,17 @@ impl

SyncCommandBufferBuilder

{ .image(resource_index); let b = &mut self.pending_barrier; - b.add_image_memory_barrier(img, 0 .. img.mipmap_levels(), + b.add_image_memory_barrier(img, + 0 .. img.mipmap_levels(), 0 .. img.dimensions().array_layers(), - entry.stages, entry.access, stages, - access, true, None, - entry.current_layout, start_layout); + entry.stages, + entry.access, + stages, + access, + true, + None, + entry.current_layout, + start_layout); }, }; } @@ -459,12 +472,18 @@ impl

SyncCommandBufferBuilder

{ unsafe { let b = &mut self.pending_barrier; - b.add_image_memory_barrier(img, 0 .. img.mipmap_levels(), + b.add_image_memory_barrier(img, + 0 .. img.mipmap_levels(), 0 .. img.dimensions().array_layers(), - PipelineStages { bottom_of_pipe: true, .. PipelineStages::none() }, // TODO:? - AccessFlagBits::none(), // TODO: ? - stages, access, - true, None, + PipelineStages { + bottom_of_pipe: true, + ..PipelineStages::none() + }, // TODO:? + AccessFlagBits::none(), // TODO: ? + stages, + access, + true, + None, img.initial_layout_requirement(), start_layout); } @@ -496,7 +515,7 @@ impl

SyncCommandBufferBuilder

{ unsafe { self.inner.pipeline_barrier(&self.pending_barrier); let f = commands_lock.first_unflushed; - for command in &mut commands_lock.commands[f..] { + for command in &mut commands_lock.commands[f ..] { command.send(&mut self.inner); } } @@ -516,11 +535,18 @@ impl

SyncCommandBufferBuilder

{ } state.exclusive_any = true; - barrier.add_image_memory_barrier(img, 0 .. img.mipmap_levels(), + barrier.add_image_memory_barrier(img, + 0 .. img.mipmap_levels(), 0 .. img.dimensions().array_layers(), - state.stages, state.access, - PipelineStages { bottom_of_pipe: true, .. PipelineStages::none() }, // TODO:? - AccessFlagBits::none(), true, None, // TODO: access? + state.stages, + state.access, + PipelineStages { + bottom_of_pipe: true, + ..PipelineStages::none() + }, // TODO:? + AccessFlagBits::none(), + true, + None, // TODO: access? state.current_layout, img.final_layout_requirement()); } @@ -539,16 +565,19 @@ impl

SyncCommandBufferBuilder

{ // Build the final resources states. let final_resources_states: FnvHashMap<_, _> = { - self.resources.into_iter().map(|(resource, state)| { - (resource.into_cb_key(final_commands.clone()), state.finalize()) - }).collect() + self.resources + .into_iter() + .map(|(resource, state)| { + (resource.into_cb_key(final_commands.clone()), state.finalize()) + }) + .collect() }; Ok(SyncCommandBuffer { - inner: self.inner.build()?, - resources: final_resources_states, - commands: final_commands, - }) + inner: self.inner.build()?, + resources: final_resources_states, + commands: final_commands, + }) } /// Calls `vkBeginRenderPass` on the builder. @@ -573,7 +602,8 @@ impl

SyncCommandBufferBuilder

{ I: Iterator { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.begin_render_pass(&self.framebuffer, self.secondary, + out.begin_render_pass(&self.framebuffer, + self.secondary, self.clear_values.take().unwrap()); } @@ -583,28 +613,28 @@ impl

SyncCommandBufferBuilder

{ where F: FramebufferAbstract + Send + Sync + 'static { fn image(&self, num: usize) -> &ImageAccess { - self.0.attachments()[num].parent() // TODO: slow + self.0.attachments()[num].parent() // TODO: slow } } Box::new(Fin(self.framebuffer)) } fn image(&self, num: usize) -> &ImageAccess { - self.framebuffer.attachments()[num].parent() // TODO: slow + self.framebuffer.attachments()[num].parent() // TODO: slow } } - let atch_desc = (0 .. framebuffer.num_attachments()).map(|atch| { - framebuffer.attachment_desc(atch).unwrap() - }).collect::>(); + let atch_desc = (0 .. framebuffer.num_attachments()) + .map(|atch| framebuffer.attachment_desc(atch).unwrap()) + .collect::>(); // FIXME: this is bad because dropping the command buffer doesn't drop the // attachments of the framebuffer, meaning that they will stay locked self.commands.lock().unwrap().commands.push(Box::new(Cmd { - framebuffer, - secondary, - clear_values: Some(clear_values), - })); + framebuffer, + secondary, + clear_values: Some(clear_values), + })); for (atch, desc) in atch_desc.into_iter().enumerate() { self.prev_cmd_resource(KeyTy::Image, atch, true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout @@ -622,7 +652,7 @@ impl

SyncCommandBufferBuilder

{ }, // TODO: suboptimal desc.initial_layout, desc.final_layout)?; } - + Ok(()) } @@ -663,21 +693,34 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer, index_ty })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { vertex_input: true, .. PipelineStages::none() }, - AccessFlagBits { index_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { buffer, index_ty })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + vertex_input: true, + ..PipelineStages::none() + }, + AccessFlagBits { + index_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; Ok(()) } - + /// Calls `vkCmdBindPipeline` on the builder with a graphics pipeline. #[inline] pub unsafe fn bind_pipeline_graphics(&mut self, pipeline: Gp) where Gp: GraphicsPipelineAbstract + Send + Sync + 'static { struct Cmd { - pipeline: Gp + pipeline: Gp, } impl Command

for Cmd @@ -697,7 +740,11 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { pipeline })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { pipeline })); } /// Calls `vkCmdBindPipeline` on the builder with a compute pipeline. @@ -706,7 +753,7 @@ impl

SyncCommandBufferBuilder

{ where Cp: ComputePipelineAbstract + Send + Sync + 'static { struct Cmd { - pipeline: Gp + pipeline: Gp, } impl Command

for Cmd @@ -726,7 +773,11 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { pipeline })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { pipeline })); } /// Starts the process of binding descriptor sets. Returns an intermediate struct which can be @@ -749,7 +800,7 @@ impl

SyncCommandBufferBuilder

{ buffers: Vec::new(), } } - + /// Calls `vkCmdCopyBuffer` on the builder. /// /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid @@ -769,11 +820,12 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where S: BufferAccess + Send + Sync + 'static, - D: BufferAccess + Send + Sync + 'static, - R: Iterator + D: BufferAccess + Send + Sync + 'static, + R: Iterator { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.copy_buffer(self.source.as_ref().unwrap(), self.destination.as_ref().unwrap(), + out.copy_buffer(self.source.as_ref().unwrap(), + self.destination.as_ref().unwrap(), self.regions.take().unwrap()); } @@ -781,43 +833,62 @@ impl

SyncCommandBufferBuilder

{ struct Fin(S, D); impl FinalCommand for Fin where S: BufferAccess + Send + Sync + 'static, - D: BufferAccess + Send + Sync + 'static, + D: BufferAccess + Send + Sync + 'static { fn buffer(&self, num: usize) -> &BufferAccess { match num { 0 => &self.0, 1 => &self.1, - _ => panic!() + _ => panic!(), } } } // Note: borrow checker somehow doesn't accept `self.source` and `self.destination` // without using an Option. - Box::new(Fin(self.source.take().unwrap(), self.destination.take().unwrap())) + Box::new(Fin(self.source.take().unwrap(), + self.destination.take().unwrap())) } fn buffer(&self, num: usize) -> &BufferAccess { match num { 0 => self.source.as_ref().unwrap(), 1 => self.destination.as_ref().unwrap(), - _ => panic!() + _ => panic!(), } } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { - source: Some(source), - destination: Some(destination), - regions: Some(regions), - })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; - self.prev_cmd_resource(KeyTy::Buffer, 1, true, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + source: Some(source), + destination: Some(destination), + regions: Some(regions), + })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; + self.prev_cmd_resource(KeyTy::Buffer, + 1, + true, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_write: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; Ok(()) } @@ -848,14 +919,15 @@ impl

SyncCommandBufferBuilder

{ unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.copy_buffer_to_image(self.source.as_ref().unwrap(), self.destination.as_ref().unwrap(), - self.dest_layout, self.regions.take().unwrap()); + self.dest_layout, + self.regions.take().unwrap()); } fn into_final_command(mut self: Box) -> Box { struct Fin(S, D); impl FinalCommand for Fin where S: BufferAccess + Send + Sync + 'static, - D: ImageAccess + Send + Sync + 'static, + D: ImageAccess + Send + Sync + 'static { fn buffer(&self, num: usize) -> &BufferAccess { assert_eq!(num, 0); @@ -870,7 +942,8 @@ impl

SyncCommandBufferBuilder

{ // Note: borrow checker somehow doesn't accept `self.source` and `self.destination` // without using an Option. - Box::new(Fin(self.source.take().unwrap(), self.destination.take().unwrap())) + Box::new(Fin(self.source.take().unwrap(), + self.destination.take().unwrap())) } fn buffer(&self, num: usize) -> &BufferAccess { @@ -885,26 +958,46 @@ impl

SyncCommandBufferBuilder

{ } self.commands.lock().unwrap().commands.push(Box::new(Cmd { - source: Some(source), - destination: Some(destination), - dest_layout, - regions: Some(regions), - })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; - self.prev_cmd_resource(KeyTy::Image, 0, true, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() }, - dest_layout, dest_layout)?; + source: Some(source), + destination: Some(destination), + dest_layout, + regions: Some(regions), + })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; + self.prev_cmd_resource(KeyTy::Image, + 0, + true, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_write: true, + ..AccessFlagBits::none() + }, + dest_layout, + dest_layout)?; Ok(()) } /// Calls `vkCmdDispatch` on the builder. #[inline] pub unsafe fn dispatch(&mut self, dimensions: [u32; 3]) { - struct Cmd { dimensions: [u32; 3] } + struct Cmd { + dimensions: [u32; 3], + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -916,7 +1009,11 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { dimensions })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { dimensions })); } /// Calls `vkCmdDispatchIndirect` on the builder. @@ -955,19 +1052,31 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { draw_indirect: true, .. PipelineStages::none() }, // TODO: is draw_indirect correct? - AccessFlagBits { indirect_command_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { buffer })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + draw_indirect: true, + ..PipelineStages::none() + }, // TODO: is draw_indirect correct? + AccessFlagBits { + indirect_command_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; Ok(()) } /// Calls `vkCmdDraw` on the builder. #[inline] pub unsafe fn draw(&mut self, vertex_count: u32, instance_count: u32, first_vertex: u32, - first_instance: u32) - { + first_instance: u32) { struct Cmd { vertex_count: u32, instance_count: u32, @@ -977,7 +1086,9 @@ impl

SyncCommandBufferBuilder

{ impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.draw(self.vertex_count, self.instance_count, self.first_vertex, + out.draw(self.vertex_count, + self.instance_count, + self.first_vertex, self.first_instance); } @@ -986,16 +1097,19 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { vertex_count, instance_count, - first_vertex, first_instance })); + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + vertex_count, + instance_count, + first_vertex, + first_instance, + })); } /// Calls `vkCmdDrawIndexed` on the builder. #[inline] - pub unsafe fn draw_indexed(&mut self, index_count: u32, instance_count: u32, first_index: u32, - vertex_offset: i32, first_instance: u32) - { + pub unsafe fn draw_indexed(&mut self, index_count: u32, instance_count: u32, + first_index: u32, vertex_offset: i32, first_instance: u32) { struct Cmd { index_count: u32, instance_count: u32, @@ -1006,8 +1120,11 @@ impl

SyncCommandBufferBuilder

{ impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.draw_indexed(self.index_count, self.instance_count, self.first_index, - self.vertex_offset, self.first_instance); + out.draw_indexed(self.index_count, + self.instance_count, + self.first_index, + self.vertex_offset, + self.first_instance); } fn into_final_command(self: Box) -> Box { @@ -1015,8 +1132,13 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { index_count, instance_count, first_index, - vertex_offset, first_instance })); + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + index_count, + instance_count, + first_index, + vertex_offset, + first_instance, + })); } /// Calls `vkCmdDrawIndirect` on the builder. @@ -1057,11 +1179,24 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer, draw_count, stride })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { draw_indirect: true, .. PipelineStages::none() }, - AccessFlagBits { indirect_command_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + buffer, + draw_count, + stride, + })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + draw_indirect: true, + ..PipelineStages::none() + }, + AccessFlagBits { + indirect_command_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; Ok(()) } @@ -1103,11 +1238,24 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer, draw_count, stride })); - self.prev_cmd_resource(KeyTy::Buffer, 0, false, - PipelineStages { draw_indirect: true, .. PipelineStages::none() }, - AccessFlagBits { indirect_command_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + buffer, + draw_count, + stride, + })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + false, + PipelineStages { + draw_indirect: true, + ..PipelineStages::none() + }, + AccessFlagBits { + indirect_command_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; Ok(()) } @@ -1165,17 +1313,33 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer, data })); - self.prev_cmd_resource(KeyTy::Buffer, 0, true, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined).unwrap(); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { buffer, data })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + true, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_write: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined) + .unwrap(); } /// Calls `vkCmdNextSubpass` on the builder. #[inline] pub unsafe fn next_subpass(&mut self, secondary: bool) { - struct Cmd { secondary: bool } + struct Cmd { + secondary: bool, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1187,7 +1351,11 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { secondary })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { secondary })); } /// Calls `vkCmdPushConstants` on the builder. @@ -1206,11 +1374,14 @@ impl

SyncCommandBufferBuilder

{ } impl Command

for Cmd - where Pl: PipelineLayoutAbstract + Send + Sync + 'static, + where Pl: PipelineLayoutAbstract + Send + Sync + 'static { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.push_constants::<_, [u8]>(&self.pipeline_layout, self.stages, self.offset, - self.size, &self.data); + out.push_constants::<_, [u8]>(&self.pipeline_layout, + self.stages, + self.offset, + self.size, + &self.data); } fn into_final_command(self: Box) -> Box { @@ -1226,17 +1397,27 @@ impl

SyncCommandBufferBuilder

{ debug_assert!(mem::size_of_val(data) >= size as usize); let mut out = Vec::with_capacity(size as usize); - ptr::copy::(data as *const D as *const u8, out.as_mut_ptr(), size as usize); + ptr::copy::(data as *const D as *const u8, + out.as_mut_ptr(), + size as usize); out.set_len(size as usize); - self.commands.lock().unwrap().commands.push(Box::new(Cmd { pipeline_layout, stages, offset, - size, data: out.into() })); + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + pipeline_layout, + stages, + offset, + size, + data: out.into(), + })); } /// Calls `vkCmdResetEvent` on the builder. #[inline] pub unsafe fn reset_event(&mut self, event: Arc, stages: PipelineStages) { - struct Cmd { event: Arc, stages: PipelineStages } + struct Cmd { + event: Arc, + stages: PipelineStages, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1245,18 +1426,25 @@ impl

SyncCommandBufferBuilder

{ fn into_final_command(self: Box) -> Box { struct Fin(Arc); - impl FinalCommand for Fin {} + impl FinalCommand for Fin { + } Box::new(Fin(self.event)) } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { event, stages })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { event, stages })); } /// Calls `vkCmdSetBlendConstants` on the builder. #[inline] pub unsafe fn set_blend_constants(&mut self, constants: [f32; 4]) { - struct Cmd { constants: [f32; 4] } + struct Cmd { + constants: [f32; 4], + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1268,13 +1456,21 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { constants })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { constants })); } /// Calls `vkCmdSetDepthBias` on the builder. #[inline] pub unsafe fn set_depth_bias(&mut self, constant_factor: f32, clamp: f32, slope_factor: f32) { - struct Cmd { constant_factor: f32, clamp: f32, slope_factor: f32 } + struct Cmd { + constant_factor: f32, + clamp: f32, + slope_factor: f32, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1286,13 +1482,20 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { constant_factor, clamp, slope_factor })); + self.commands.lock().unwrap().commands.push(Box::new(Cmd { + constant_factor, + clamp, + slope_factor, + })); } /// Calls `vkCmdSetDepthBounds` on the builder. #[inline] pub unsafe fn set_depth_bounds(&mut self, min: f32, max: f32) { - struct Cmd { min: f32, max: f32 } + struct Cmd { + min: f32, + max: f32, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1304,13 +1507,20 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { min, max })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { min, max })); } /// Calls `vkCmdSetEvent` on the builder. #[inline] pub unsafe fn set_event(&mut self, event: Arc, stages: PipelineStages) { - struct Cmd { event: Arc, stages: PipelineStages } + struct Cmd { + event: Arc, + stages: PipelineStages, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1319,18 +1529,25 @@ impl

SyncCommandBufferBuilder

{ fn into_final_command(self: Box) -> Box { struct Fin(Arc); - impl FinalCommand for Fin {} + impl FinalCommand for Fin { + } Box::new(Fin(self.event)) } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { event, stages })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { event, stages })); } /// Calls `vkCmdSetLineWidth` on the builder. #[inline] pub unsafe fn set_line_width(&mut self, line_width: f32) { - struct Cmd { line_width: f32 } + struct Cmd { + line_width: f32, + } impl

Command

for Cmd { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { @@ -1342,7 +1559,11 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { line_width })); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { line_width })); } // TODO: stencil states @@ -1354,7 +1575,10 @@ impl

SyncCommandBufferBuilder

{ pub unsafe fn set_scissor(&mut self, first_scissor: u32, scissors: I) where I: Iterator + Send + Sync + 'static { - struct Cmd { first_scissor: u32, scissors: Option } + struct Cmd { + first_scissor: u32, + scissors: Option, + } impl Command

for Cmd where I: Iterator @@ -1369,9 +1593,9 @@ impl

SyncCommandBufferBuilder

{ } self.commands.lock().unwrap().commands.push(Box::new(Cmd { - first_scissor, - scissors: Some(scissors), - })); + first_scissor, + scissors: Some(scissors), + })); } /// Calls `vkCmdSetViewport` on the builder. @@ -1381,7 +1605,10 @@ impl

SyncCommandBufferBuilder

{ pub unsafe fn set_viewport(&mut self, first_viewport: u32, viewports: I) where I: Iterator + Send + Sync + 'static { - struct Cmd { first_viewport: u32, viewports: Option } + struct Cmd { + first_viewport: u32, + viewports: Option, + } impl Command

for Cmd where I: Iterator @@ -1396,9 +1623,9 @@ impl

SyncCommandBufferBuilder

{ } self.commands.lock().unwrap().commands.push(Box::new(Cmd { - first_viewport, - viewports: Some(viewports), - })); + first_viewport, + viewports: Some(viewports), + })); } /// Calls `vkCmdUpdateBuffer` on the builder. @@ -1439,11 +1666,25 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd { buffer, data })); - self.prev_cmd_resource(KeyTy::Buffer, 0, true, - PipelineStages { transfer: true, .. PipelineStages::none() }, - AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined).unwrap(); + self.commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { buffer, data })); + self.prev_cmd_resource(KeyTy::Buffer, + 0, + true, + PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + AccessFlagBits { + transfer_write: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined) + .unwrap(); } } @@ -1473,7 +1714,7 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { dynamic_offsets: I) -> Result<(), SyncCommandBufferBuilderError> where Pl: PipelineLayoutAbstract + Send + Sync + 'static, - I: Iterator + Send + Sync + 'static, + I: Iterator + Send + Sync + 'static { struct Cmd { inner: SmallVec<[Box; 12]>, @@ -1488,25 +1729,34 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { I: Iterator { unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { - out.bind_descriptor_sets(self.graphics, &self.pipeline_layout, self.first_binding, + out.bind_descriptor_sets(self.graphics, + &self.pipeline_layout, + self.first_binding, self.inner.iter().map(|s| s.inner()), self.dynamic_offsets.take().unwrap()); } fn into_final_command(self: Box) -> Box { struct Fin(SmallVec<[Box; 12]>); - impl FinalCommand for Fin { /* TODO: implement buffer() and image() */ } + impl FinalCommand for Fin { + /* TODO: implement buffer() and image() */ + } Box::new(Fin(self.inner)) } } - self.builder.commands.lock().unwrap().commands.push(Box::new(Cmd { - inner: self.inner, - graphics, - pipeline_layout, - first_binding, - dynamic_offsets: Some(dynamic_offsets), - })); + self.builder + .commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { + inner: self.inner, + graphics, + pipeline_layout, + first_binding, + dynamic_offsets: Some(dynamic_offsets), + })); // FIXME: add resources @@ -1561,17 +1811,32 @@ impl<'a, P> SyncCommandBufferBuilderBindVertexBuffer<'a, P> { let num_buffers = self.buffers.len(); - self.builder.commands.lock().unwrap().commands.push(Box::new(Cmd { - first_binding, - inner: Some(self.inner), - buffers: self.buffers, - })); + self.builder + .commands + .lock() + .unwrap() + .commands + .push(Box::new(Cmd { + first_binding, + inner: Some(self.inner), + buffers: self.buffers, + })); for n in 0 .. num_buffers { - self.builder.prev_cmd_resource(KeyTy::Buffer, n, false, - PipelineStages { vertex_input: true, .. PipelineStages::none() }, - AccessFlagBits { vertex_attribute_read: true, .. AccessFlagBits::none() }, - ImageLayout::Undefined, ImageLayout::Undefined)?; + self.builder + .prev_cmd_resource(KeyTy::Buffer, + n, + false, + PipelineStages { + vertex_input: true, + ..PipelineStages::none() + }, + AccessFlagBits { + vertex_attribute_read: true, + ..AccessFlagBits::none() + }, + ImageLayout::Undefined, + ImageLayout::Undefined)?; } Ok(()) @@ -1607,19 +1872,24 @@ struct ResourceFinalState { initial_layout: ImageLayout, // Layout the image will be in at the end of the command buffer. - final_layout: ImageLayout, // TODO: maybe wrap in an Option to mean that the layout doesn't change? because of buffers? + final_layout: ImageLayout, // TODO: maybe wrap in an Option to mean that the layout doesn't change? because of buffers? } /// Equivalent to `Command`, but with less methods. Typically contains less things than the /// `Command` it comes from. trait FinalCommand { // Gives access to the `num`th buffer used by the command. - fn buffer(&self, num: usize) -> &BufferAccess { panic!() } + fn buffer(&self, num: usize) -> &BufferAccess { + panic!() + } // Gives access to the `num`th image used by the command. - fn image(&self, num: usize) -> &ImageAccess { panic!() } + fn image(&self, num: usize) -> &ImageAccess { + panic!() + } } -impl FinalCommand for () {} +impl FinalCommand for () { +} // Equivalent of `BuilderKey` for a finished command buffer. // @@ -1649,20 +1919,30 @@ enum CbKey<'a> { // because it would be too constraining. // Since only `CbKey::Command` must be stored in the resources hashmap, we force-implement `Send` // and `Sync` so that the hashmap itself implements `Send` and `Sync`. -unsafe impl<'a> Send for CbKey<'a> {} -unsafe impl<'a> Sync for CbKey<'a> {} +unsafe impl<'a> Send for CbKey<'a> { +} +unsafe impl<'a> Sync for CbKey<'a> { +} impl<'a> CbKey<'a> { #[inline] fn conflicts_buffer_all(&self, commands_lock: Option<&Vec>>, - buf: &BufferAccess) -> bool - { + buf: &BufferAccess) + -> bool { match *self { - CbKey::Command { ref commands, command_id, resource_ty, resource_index } => { - let lock = if commands_lock.is_none() { Some(commands.lock().unwrap()) } - else { None }; + CbKey::Command { + ref commands, + command_id, + resource_ty, + resource_index, + } => { + let lock = if commands_lock.is_none() { + Some(commands.lock().unwrap()) + } else { + None + }; let commands_lock = commands_lock.unwrap_or_else(|| lock.as_ref().unwrap()); - + // TODO: put the conflicts_* methods directly on the FinalCommand trait to avoid an indirect call? match resource_ty { KeyTy::Buffer => { @@ -1683,14 +1963,22 @@ impl<'a> CbKey<'a> { #[inline] fn conflicts_image_all(&self, commands_lock: Option<&Vec>>, - img: &ImageAccess) -> bool - { + img: &ImageAccess) + -> bool { match *self { - CbKey::Command { ref commands, command_id, resource_ty, resource_index } => { - let lock = if commands_lock.is_none() { Some(commands.lock().unwrap()) } - else { None }; + CbKey::Command { + ref commands, + command_id, + resource_ty, + resource_index, + } => { + let lock = if commands_lock.is_none() { + Some(commands.lock().unwrap()) + } else { + None + }; let commands_lock = commands_lock.unwrap_or_else(|| lock.as_ref().unwrap()); - + // TODO: put the conflicts_* methods directly on the Command trait to avoid an indirect call? match resource_ty { KeyTy::Buffer => { @@ -1720,7 +2008,12 @@ impl<'a> PartialEq for CbKey<'a> { CbKey::ImageRef(a) => { other.conflicts_image_all(None, a) }, - CbKey::Command { ref commands, command_id, resource_ty, resource_index } => { + CbKey::Command { + ref commands, + command_id, + resource_ty, + resource_index, + } => { let commands_lock = commands.lock().unwrap(); match resource_ty { @@ -1745,7 +2038,12 @@ impl<'a> Hash for CbKey<'a> { #[inline] fn hash(&self, state: &mut H) { match *self { - CbKey::Command { ref commands, command_id, resource_ty, resource_index } => { + CbKey::Command { + ref commands, + command_id, + resource_ty, + resource_index, + } => { let commands_lock = commands.lock().unwrap(); match resource_ty { @@ -1774,17 +2072,23 @@ unsafe impl

CommandBuffer for SyncCommandBuffer

{ &self.inner } - fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> { + fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) + -> Result<(), CommandBufferExecError> { // TODO: if at any point we return an error, we can't recover let commands_lock = self.commands.lock().unwrap(); for (key, entry) in self.resources.iter() { let (commands, command_id, resource_ty, resource_index) = match *key { - CbKey::Command { ref commands, command_id, resource_ty, resource_index } => { + CbKey::Command { + ref commands, + command_id, + resource_ty, + resource_index, + } => { (commands, command_id, resource_ty, resource_index) }, - _ => unreachable!() + _ => unreachable!(), }; match resource_ty { @@ -1794,10 +2098,12 @@ unsafe impl

CommandBuffer for SyncCommandBuffer

{ let prev_err = match future.check_buffer_access(&buf, entry.exclusive, queue) { Ok(_) => { - unsafe { buf.increase_gpu_lock(); } + unsafe { + buf.increase_gpu_lock(); + } continue; }, - Err(err) => err + Err(err) => err, }; match (buf.try_gpu_lock(entry.exclusive, queue), prev_err) { @@ -1835,9 +2141,9 @@ unsafe impl

CommandBuffer for SyncCommandBuffer

{ } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { // TODO: check the queue family if let Some(value) = self.resources.get(&CbKey::BufferRef(buffer)) { @@ -1852,17 +2158,17 @@ unsafe impl

CommandBuffer for SyncCommandBuffer

{ } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { // TODO: check the queue family if let Some(value) = self.resources.get(&CbKey::ImageRef(image)) { if layout != ImageLayout::Undefined && value.final_layout != layout { return Err(AccessCheckError::Denied(AccessError::UnexpectedImageLayout { - allowed: value.final_layout, - requested: layout, - })); + allowed: value.final_layout, + requested: layout, + })); } if !value.exclusive && exclusive { @@ -1890,10 +2196,15 @@ impl

Drop for SyncCommandBuffer

{ for (key, entry) in self.resources.iter() { let (command_id, resource_ty, resource_index) = match *key { - CbKey::Command { command_id, resource_ty, resource_index, .. } => { + CbKey::Command { + command_id, + resource_ty, + resource_index, + .. + } => { (command_id, resource_ty, resource_index) }, - _ => unreachable!() + _ => unreachable!(), }; match resource_ty { diff --git a/vulkano/src/command_buffer/sys.rs b/vulkano/src/command_buffer/sys.rs index 7392fe58..5059aca4 100644 --- a/vulkano/src/command_buffer/sys.rs +++ b/vulkano/src/command_buffer/sys.rs @@ -7,23 +7,26 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::fmt; use std::mem; use std::ops::Range; use std::ptr; use std::sync::Arc; use std::sync::atomic::AtomicBool; -use smallvec::SmallVec; +use OomError; +use VulkanObject; use buffer::BufferAccess; use buffer::BufferInner; +use check_errors; use command_buffer::CommandBuffer; use command_buffer::pool::CommandPool; -use command_buffer::pool::CommandPoolBuilderAlloc; use command_buffer::pool::CommandPoolAlloc; +use command_buffer::pool::CommandPoolBuilderAlloc; use descriptor::descriptor::ShaderStages; -use descriptor::pipeline_layout::PipelineLayoutAbstract; use descriptor::descriptor_set::UnsafeDescriptorSet; +use descriptor::pipeline_layout::PipelineLayoutAbstract; use device::Device; use device::DeviceOwned; use format::ClearValue; @@ -33,8 +36,8 @@ use framebuffer::FramebufferAbstract; use framebuffer::RenderPass; use framebuffer::RenderPassAbstract; use framebuffer::Subpass; -use image::ImageLayout; use image::ImageAccess; +use image::ImageLayout; use instance::QueueFamily; use pipeline::ComputePipelineAbstract; use pipeline::GraphicsPipelineAbstract; @@ -42,11 +45,8 @@ use pipeline::input_assembly::IndexType; use pipeline::viewport::Scissor; use pipeline::viewport::Viewport; use sync::AccessFlagBits; -use sync::PipelineStages; use sync::Event; -use OomError; -use VulkanObject; -use check_errors; +use sync::PipelineStages; use vk; /// Determines the kind of command buffer that we want to create. @@ -71,24 +71,32 @@ pub enum Kind { }, } -impl Kind, Framebuffer, ()>> { +impl + Kind, + Framebuffer, ()>> { /// Equivalent to `Kind::Primary`. /// /// > **Note**: If you use `let kind = Kind::Primary;` in your code, you will probably get a /// > compilation error because the Rust compiler couldn't determine the template parameters /// > of `Kind`. To solve that problem in an easy way you can use this function instead. #[inline] - pub fn primary() -> Kind, Framebuffer, ()>> { + pub fn primary() + -> Kind, + Framebuffer, ()>> + { Kind::Primary } - + /// Equivalent to `Kind::Secondary`. /// /// > **Note**: If you use `let kind = Kind::Secondary;` in your code, you will probably get a /// > compilation error because the Rust compiler couldn't determine the template parameters /// > of `Kind`. To solve that problem in an easy way you can use this function instead. #[inline] - pub fn secondary() -> Kind, Framebuffer, ()>> { + pub fn secondary() + -> Kind, + Framebuffer, ()>> + { Kind::Secondary } } @@ -155,7 +163,7 @@ impl

UnsafeCommandBufferBuilder

{ /// > **Note**: Some checks are still made with `debug_assert!`. Do not expect to be able to /// > submit invalid commands. pub unsafe fn new(pool: &Pool, kind: Kind, flags: Flags) - -> Result, OomError> + -> Result, OomError> where Pool: CommandPool, P: CommandPoolBuilderAlloc, A: CommandPoolAlloc, @@ -164,11 +172,13 @@ impl

UnsafeCommandBufferBuilder

{ { let secondary = match kind { Kind::Primary => false, - Kind::Secondary | Kind::SecondaryRenderPass { .. } => true, + Kind::Secondary | + Kind::SecondaryRenderPass { .. } => true, }; - let cmd = try!(pool.alloc(secondary, 1)).next().expect("Requested one command buffer from \ - the command pool, but got zero."); + let cmd = pool.alloc(secondary, 1)? + .next() + .expect("Requested one command buffer from the command pool, but got zero."); UnsafeCommandBufferBuilder::already_allocated(cmd, kind, flags) } @@ -213,7 +223,11 @@ impl

UnsafeCommandBufferBuilder

{ (0, 0) }; - let framebuffer = if let Kind::SecondaryRenderPass { ref subpass, framebuffer: Some(ref framebuffer) } = kind { + let framebuffer = if let Kind::SecondaryRenderPass { + ref subpass, + framebuffer: Some(ref framebuffer), + } = kind + { // TODO: restore check //assert!(framebuffer.is_compatible_with(subpass.render_pass())); // TODO: proper error FramebufferAbstract::inner(&framebuffer).internal_object() @@ -227,9 +241,9 @@ impl

UnsafeCommandBufferBuilder

{ renderPass: rp, subpass: sp, framebuffer: framebuffer, - occlusionQueryEnable: 0, // TODO: - queryFlags: 0, // TODO: - pipelineStatistics: 0, // TODO: + occlusionQueryEnable: 0, // TODO: + queryFlags: 0, // TODO: + pipelineStatistics: 0, // TODO: }; let infos = vk::CommandBufferBeginInfo { @@ -239,14 +253,14 @@ impl

UnsafeCommandBufferBuilder

{ pInheritanceInfo: &inheritance, }; - try!(check_errors(vk.BeginCommandBuffer(cmd, &infos))); + check_errors(vk.BeginCommandBuffer(cmd, &infos))?; Ok(UnsafeCommandBufferBuilder { - cmd: Some(alloc), - cmd_raw: cmd, - device: device.clone(), - flags: flags, - }) + cmd: Some(alloc), + cmd_raw: cmd, + device: device.clone(), + flags: flags, + }) } /// Returns the queue family of the builder. @@ -260,21 +274,21 @@ impl

UnsafeCommandBufferBuilder

{ /// Turns the builder into an actual command buffer. #[inline] pub fn build(mut self) -> Result, OomError> - where P: CommandPoolBuilderAlloc + where P: CommandPoolBuilderAlloc { unsafe { let cmd = self.cmd.take().unwrap(); let vk = self.device.pointers(); - try!(check_errors(vk.EndCommandBuffer(cmd.inner().internal_object()))); + check_errors(vk.EndCommandBuffer(cmd.inner().internal_object()))?; let cmd_raw = cmd.inner().internal_object(); Ok(UnsafeCommandBuffer { - cmd: cmd.into_alloc(), - cmd_raw: cmd_raw, - device: self.device.clone(), - flags: self.flags, - already_submitted: AtomicBool::new(false), - }) + cmd: cmd.into_alloc(), + cmd_raw: cmd_raw, + device: self.device.clone(), + flags: self.flags, + already_submitted: AtomicBool::new(false), + }) } } @@ -293,41 +307,46 @@ impl

UnsafeCommandBufferBuilder

{ let raw_render_pass = RenderPassAbstract::inner(&framebuffer).internal_object(); let raw_framebuffer = FramebufferAbstract::inner(&framebuffer).internal_object(); - let raw_clear_values: SmallVec<[_; 12]> = clear_values.map(|clear_value| { - match clear_value { - ClearValue::None => { - vk::ClearValue::color(vk::ClearColorValue::float32([0.0; 4])) - }, - ClearValue::Float(val) => { - vk::ClearValue::color(vk::ClearColorValue::float32(val)) - }, - ClearValue::Int(val) => { - vk::ClearValue::color(vk::ClearColorValue::int32(val)) - }, - ClearValue::Uint(val) => { - vk::ClearValue::color(vk::ClearColorValue::uint32(val)) - }, - ClearValue::Depth(val) => { - vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { - depth: val, stencil: 0 - }) - }, - ClearValue::Stencil(val) => { - vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { - depth: 0.0, stencil: val - }) - }, - ClearValue::DepthStencil((depth, stencil)) => { - vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { - depth: depth, stencil: stencil, - }) - }, - } - }).collect(); + let raw_clear_values: SmallVec<[_; 12]> = clear_values + .map(|clear_value| match clear_value { + ClearValue::None => { + vk::ClearValue::color(vk::ClearColorValue::float32([0.0; 4])) + }, + ClearValue::Float(val) => { + vk::ClearValue::color(vk::ClearColorValue::float32(val)) + }, + ClearValue::Int(val) => { + vk::ClearValue::color(vk::ClearColorValue::int32(val)) + }, + ClearValue::Uint(val) => { + vk::ClearValue::color(vk::ClearColorValue::uint32(val)) + }, + ClearValue::Depth(val) => { + vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { + depth: val, + stencil: 0, + }) + }, + ClearValue::Stencil(val) => { + vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { + depth: 0.0, + stencil: val, + }) + }, + ClearValue::DepthStencil((depth, stencil)) => { + vk::ClearValue::depth_stencil(vk::ClearDepthStencilValue { + depth: depth, + stencil: stencil, + }) + }, + }) + .collect(); // TODO: allow customizing - let rect = [0 .. framebuffer.dimensions()[0], - 0 .. framebuffer.dimensions()[1]]; + let rect = [ + 0 .. framebuffer.dimensions()[0], + 0 .. framebuffer.dimensions()[1], + ]; let begin = vk::RenderPassBeginInfo { sType: vk::STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, @@ -347,9 +366,12 @@ impl

UnsafeCommandBufferBuilder

{ clearValueCount: raw_clear_values.len() as u32, pClearValues: raw_clear_values.as_ptr(), }; - - let contents = if secondary { vk::SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS } - else { vk::SUBPASS_CONTENTS_INLINE }; + + let contents = if secondary { + vk::SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS + } else { + vk::SUBPASS_CONTENTS_INLINE + }; vk.CmdBeginRenderPass(cmd, &begin, contents); } @@ -364,7 +386,7 @@ impl

UnsafeCommandBufferBuilder

{ sets: S, dynamic_offsets: I) where Pl: ?Sized + PipelineLayoutAbstract, S: Iterator, - I: Iterator, + I: Iterator { let vk = self.device().pointers(); let cmd = self.internal_object(); @@ -378,12 +400,20 @@ impl

UnsafeCommandBufferBuilder

{ let num_bindings = sets.len() as u32; debug_assert!(first_binding + num_bindings <= pipeline_layout.num_sets() as u32); - let bind_point = if graphics { vk::PIPELINE_BIND_POINT_GRAPHICS } - else { vk::PIPELINE_BIND_POINT_COMPUTE }; + let bind_point = if graphics { + vk::PIPELINE_BIND_POINT_GRAPHICS + } else { + vk::PIPELINE_BIND_POINT_COMPUTE + }; - vk.CmdBindDescriptorSets(cmd, bind_point, pipeline_layout.sys().internal_object(), - first_binding, num_bindings, sets.as_ptr(), - dynamic_offsets.len() as u32, dynamic_offsets.as_ptr()); + vk.CmdBindDescriptorSets(cmd, + bind_point, + pipeline_layout.sys().internal_object(), + first_binding, + num_bindings, + sets.as_ptr(), + dynamic_offsets.len() as u32, + dynamic_offsets.as_ptr()); } /// Calls `vkCmdBindIndexBuffer` on the builder. @@ -398,7 +428,9 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(inner.offset < inner.buffer.size()); debug_assert!(inner.buffer.usage_index_buffer()); - vk.CmdBindIndexBuffer(cmd, inner.buffer.internal_object(), inner.offset as vk::DeviceSize, + vk.CmdBindIndexBuffer(cmd, + inner.buffer.internal_object(), + inner.offset as vk::DeviceSize, index_ty as vk::IndexType); } @@ -409,7 +441,8 @@ impl

UnsafeCommandBufferBuilder

{ { let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdBindPipeline(cmd, vk::PIPELINE_BIND_POINT_COMPUTE, + vk.CmdBindPipeline(cmd, + vk::PIPELINE_BIND_POINT_COMPUTE, pipeline.inner().internal_object()); } @@ -430,8 +463,7 @@ impl

UnsafeCommandBufferBuilder

{ /// usage of the command anyway. #[inline] pub unsafe fn bind_vertex_buffers(&mut self, first_binding: u32, - params: UnsafeCommandBufferBuilderBindVertexBuffer) - { + params: UnsafeCommandBufferBuilderBindVertexBuffer) { debug_assert_eq!(params.raw_buffers.len(), params.offsets.len()); if params.raw_buffers.is_empty() { @@ -444,11 +476,17 @@ impl

UnsafeCommandBufferBuilder

{ let num_bindings = params.raw_buffers.len() as u32; debug_assert!({ - let max_bindings = self.device().physical_device().limits().max_vertex_input_bindings(); - first_binding + num_bindings <= max_bindings - }); + let max_bindings = self.device() + .physical_device() + .limits() + .max_vertex_input_bindings(); + first_binding + num_bindings <= max_bindings + }); - vk.CmdBindVertexBuffers(cmd, first_binding, num_bindings, params.raw_buffers.as_ptr(), + vk.CmdBindVertexBuffers(cmd, + first_binding, + num_bindings, + params.raw_buffers.as_ptr(), params.offsets.as_ptr()); } @@ -495,13 +533,15 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(destination.offset < destination.buffer.size()); debug_assert!(destination.buffer.usage_transfer_dest()); - let regions: SmallVec<[_; 8]> = regions.map(|(sr, de, sz)| { - vk::BufferCopy { - srcOffset: (sr + source.offset) as vk::DeviceSize, - dstOffset: (de + destination.offset) as vk::DeviceSize, - size: sz as vk::DeviceSize, - } - }).collect(); + let regions: SmallVec<[_; 8]> = regions + .map(|(sr, de, sz)| { + vk::BufferCopy { + srcOffset: (sr + source.offset) as vk::DeviceSize, + dstOffset: (de + destination.offset) as vk::DeviceSize, + size: sz as vk::DeviceSize, + } + }) + .collect(); if regions.is_empty() { return; @@ -509,8 +549,11 @@ impl

UnsafeCommandBufferBuilder

{ let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdCopyBuffer(cmd, source.buffer.internal_object(), destination.buffer.internal_object(), - regions.len() as u32, regions.as_ptr()); + vk.CmdCopyBuffer(cmd, + source.buffer.internal_object(), + destination.buffer.internal_object(), + regions.len() as u32, + regions.as_ptr()); } /// Calls `vkCmdCopyBufferToImage` on the builder. @@ -528,29 +571,31 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(source.offset < source.buffer.size()); debug_assert!(source.buffer.usage_transfer_src()); - let regions: SmallVec<[_; 8]> = regions.map(|copy| { - vk::BufferImageCopy { - bufferOffset: (source.offset + copy.buffer_offset) as vk::DeviceSize, - bufferRowLength: copy.buffer_row_length, - bufferImageHeight: copy.buffer_image_height, - imageSubresource: vk::ImageSubresourceLayers { - aspectMask: copy.image_aspect.to_vk_bits(), - mipLevel: copy.image_mip_level, - baseArrayLayer: copy.image_base_array_layer, - layerCount: copy.image_layer_count, - }, - imageOffset: vk::Offset3D { - x: copy.image_offset[0], - y: copy.image_offset[1], - z: copy.image_offset[2], - }, - imageExtent: vk::Extent3D { - width: copy.image_extent[0], - height: copy.image_extent[1], - depth: copy.image_extent[2], - }, - } - }).collect(); + let regions: SmallVec<[_; 8]> = regions + .map(|copy| { + vk::BufferImageCopy { + bufferOffset: (source.offset + copy.buffer_offset) as vk::DeviceSize, + bufferRowLength: copy.buffer_row_length, + bufferImageHeight: copy.buffer_image_height, + imageSubresource: vk::ImageSubresourceLayers { + aspectMask: copy.image_aspect.to_vk_bits(), + mipLevel: copy.image_mip_level, + baseArrayLayer: copy.image_base_array_layer, + layerCount: copy.image_layer_count, + }, + imageOffset: vk::Offset3D { + x: copy.image_offset[0], + y: copy.image_offset[1], + z: copy.image_offset[2], + }, + imageExtent: vk::Extent3D { + width: copy.image_extent[0], + height: copy.image_extent[1], + depth: copy.image_extent[2], + }, + } + }) + .collect(); if regions.is_empty() { return; @@ -559,23 +604,29 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(destination.inner().usage_transfer_dest()); debug_assert_eq!(destination.samples(), 1); debug_assert!(dest_layout == ImageLayout::General || - dest_layout == ImageLayout::TransferDstOptimal); + dest_layout == ImageLayout::TransferDstOptimal); let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdCopyBufferToImage(cmd, source.buffer.internal_object(), - destination.inner().internal_object(), dest_layout as u32, - regions.len() as u32, regions.as_ptr()); + vk.CmdCopyBufferToImage(cmd, + source.buffer.internal_object(), + destination.inner().internal_object(), + dest_layout as u32, + regions.len() as u32, + regions.as_ptr()); } /// Calls `vkCmdDispatch` on the builder. #[inline] pub unsafe fn dispatch(&mut self, dimensions: [u32; 3]) { debug_assert!({ - let max_dims = self.device().physical_device().limits().max_compute_work_group_count(); - dimensions[0] <= max_dims[0] && dimensions[1] <= max_dims[1] && - dimensions[2] <= max_dims[2] - }); + let max_dims = self.device() + .physical_device() + .limits() + .max_compute_work_group_count(); + dimensions[0] <= max_dims[0] && dimensions[1] <= max_dims[1] && + dimensions[2] <= max_dims[2] + }); let vk = self.device().pointers(); let cmd = self.internal_object(); @@ -595,27 +646,35 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(inner.buffer.usage_indirect_buffer()); debug_assert_eq!(inner.offset % 4, 0); - vk.CmdDispatchIndirect(cmd, inner.buffer.internal_object(), inner.offset as vk::DeviceSize); + vk.CmdDispatchIndirect(cmd, + inner.buffer.internal_object(), + inner.offset as vk::DeviceSize); } /// Calls `vkCmdDraw` on the builder. #[inline] pub unsafe fn draw(&mut self, vertex_count: u32, instance_count: u32, first_vertex: u32, - first_instance: u32) - { + first_instance: u32) { let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdDraw(cmd, vertex_count, instance_count, first_vertex, first_instance); + vk.CmdDraw(cmd, + vertex_count, + instance_count, + first_vertex, + first_instance); } /// Calls `vkCmdDrawIndexed` on the builder. #[inline] - pub unsafe fn draw_indexed(&mut self, index_count: u32, instance_count: u32, first_index: u32, - vertex_offset: i32, first_instance: u32) - { + pub unsafe fn draw_indexed(&mut self, index_count: u32, instance_count: u32, + first_index: u32, vertex_offset: i32, first_instance: u32) { let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, + vk.CmdDrawIndexed(cmd, + index_count, + instance_count, + first_index, + vertex_offset, first_instance); } @@ -627,15 +686,19 @@ impl

UnsafeCommandBufferBuilder

{ let vk = self.device().pointers(); let cmd = self.internal_object(); - debug_assert!(draw_count == 0 || ((stride % 4) == 0) && - stride as usize >= mem::size_of::()); - + debug_assert!(draw_count == 0 || + ((stride % 4) == 0) && + stride as usize >= mem::size_of::()); + let inner = buffer.inner(); debug_assert!(inner.offset < buffer.size()); debug_assert!(inner.buffer.usage_indirect_buffer()); - vk.CmdDrawIndirect(cmd, inner.buffer.internal_object(), inner.offset as vk::DeviceSize, - draw_count, stride); + vk.CmdDrawIndirect(cmd, + inner.buffer.internal_object(), + inner.offset as vk::DeviceSize, + draw_count, + stride); } /// Calls `vkCmdDrawIndexedIndirect` on the builder. @@ -645,13 +708,16 @@ impl

UnsafeCommandBufferBuilder

{ { let vk = self.device().pointers(); let cmd = self.internal_object(); - + let inner = buffer.inner(); debug_assert!(inner.offset < buffer.size()); debug_assert!(inner.buffer.usage_indirect_buffer()); - vk.CmdDrawIndexedIndirect(cmd, inner.buffer.internal_object(), - inner.offset as vk::DeviceSize, draw_count, stride); + vk.CmdDrawIndexedIndirect(cmd, + inner.buffer.internal_object(), + inner.offset as vk::DeviceSize, + draw_count, + stride); } /// Calls `vkCmdEndRenderPass` on the builder. @@ -688,14 +754,20 @@ impl

UnsafeCommandBufferBuilder

{ let size = buffer.size(); let (buffer_handle, offset) = { - let BufferInner { buffer: buffer_inner, offset } = buffer.inner(); + let BufferInner { + buffer: buffer_inner, + offset, + } = buffer.inner(); debug_assert!(buffer_inner.usage_transfer_dest()); debug_assert_eq!(offset % 4, 0); (buffer_inner.internal_object(), offset) }; - vk.CmdFillBuffer(cmd, buffer_handle, offset as vk::DeviceSize, - size as vk::DeviceSize, data); + vk.CmdFillBuffer(cmd, + buffer_handle, + offset as vk::DeviceSize, + size as vk::DeviceSize, + data); } /// Calls `vkCmdNextSubpass` on the builder. @@ -705,8 +777,11 @@ impl

UnsafeCommandBufferBuilder

{ let vk = self.device().pointers(); let cmd = self.internal_object(); - let contents = if secondary { vk::SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS } - else { vk::SUBPASS_CONTENTS_INLINE }; + let contents = if secondary { + vk::SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS + } else { + vk::SUBPASS_CONTENTS_INLINE + }; vk.CmdNextSubpass(cmd, contents); } @@ -727,8 +802,11 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert_ne!(command.src_stage_mask, 0); debug_assert_ne!(command.dst_stage_mask, 0); - vk.CmdPipelineBarrier(cmd, command.src_stage_mask, command.dst_stage_mask, - command.dependency_flags, command.memory_barriers.len() as u32, + vk.CmdPipelineBarrier(cmd, + command.src_stage_mask, + command.dst_stage_mask, + command.dependency_flags, + command.memory_barriers.len() as u32, command.memory_barriers.as_ptr(), command.buffer_barriers.len() as u32, command.buffer_barriers.as_ptr(), @@ -752,8 +830,11 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert_eq!(offset % 4, 0); debug_assert!(mem::size_of_val(data) >= size as usize); - vk.CmdPushConstants(cmd, pipeline_layout.sys().internal_object(), - stages.into(), offset as u32, size as u32, + vk.CmdPushConstants(cmd, + pipeline_layout.sys().internal_object(), + stages.into(), + offset as u32, + size as u32, data as *const D as *const _); } @@ -774,7 +855,7 @@ impl

UnsafeCommandBufferBuilder

{ pub unsafe fn set_blend_constants(&mut self, constants: [f32; 4]) { let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdSetBlendConstants(cmd, constants); // TODO: correct to pass array? + vk.CmdSetBlendConstants(cmd, constants); // TODO: correct to pass array? } /// Calls `vkCmdSetDepthBias` on the builder. @@ -851,18 +932,20 @@ impl

UnsafeCommandBufferBuilder

{ pub unsafe fn set_scissor(&mut self, first_scissor: u32, scissors: I) where I: Iterator { - let scissors = scissors.map(|v| v.clone().into()).collect::>(); + let scissors = scissors + .map(|v| v.clone().into()) + .collect::>(); if scissors.is_empty() { return; } // TODO: missing a debug assert for limits on the actual scissor values debug_assert!((first_scissor == 0 && scissors.len() == 1) || - self.device().enabled_features().multi_viewport); + self.device().enabled_features().multi_viewport); debug_assert!({ - let max = self.device().physical_device().limits().max_viewports(); - first_scissor + scissors.len() as u32 <= max - }); + let max = self.device().physical_device().limits().max_viewports(); + first_scissor + scissors.len() as u32 <= max + }); let vk = self.device().pointers(); let cmd = self.internal_object(); @@ -876,21 +959,26 @@ impl

UnsafeCommandBufferBuilder

{ pub unsafe fn set_viewport(&mut self, first_viewport: u32, viewports: I) where I: Iterator { - let viewports = viewports.map(|v| v.clone().into()).collect::>(); + let viewports = viewports + .map(|v| v.clone().into()) + .collect::>(); if viewports.is_empty() { return; } debug_assert!((first_viewport == 0 && viewports.len() == 1) || - self.device().enabled_features().multi_viewport); + self.device().enabled_features().multi_viewport); debug_assert!({ - let max = self.device().physical_device().limits().max_viewports(); - first_viewport + viewports.len() as u32 <= max - }); + let max = self.device().physical_device().limits().max_viewports(); + first_viewport + viewports.len() as u32 <= max + }); let vk = self.device().pointers(); let cmd = self.internal_object(); - vk.CmdSetViewport(cmd, first_viewport, viewports.len() as u32, viewports.as_ptr()); + vk.CmdSetViewport(cmd, + first_viewport, + viewports.len() as u32, + viewports.as_ptr()); } /// Calls `vkCmdUpdateBuffer` on the builder. @@ -908,13 +996,19 @@ impl

UnsafeCommandBufferBuilder

{ debug_assert!(size <= mem::size_of_val(data)); let (buffer_handle, offset) = { - let BufferInner { buffer: buffer_inner, offset } = buffer.inner(); + let BufferInner { + buffer: buffer_inner, + offset, + } = buffer.inner(); debug_assert!(buffer_inner.usage_transfer_dest()); debug_assert_eq!(offset % 4, 0); (buffer_inner.internal_object(), offset) }; - vk.CmdUpdateBuffer(cmd, buffer_handle, offset as vk::DeviceSize, size as vk::DeviceSize, + vk.CmdUpdateBuffer(cmd, + buffer_handle, + offset as vk::DeviceSize, + size as vk::DeviceSize, data as *const D as *const _); } } @@ -976,9 +1070,7 @@ impl UnsafeCommandBufferBuilderExecuteCommands { /// Builds a new empty list. #[inline] pub fn new() -> UnsafeCommandBufferBuilderExecuteCommands { - UnsafeCommandBufferBuilderExecuteCommands { - raw_cbs: SmallVec::new(), - } + UnsafeCommandBufferBuilderExecuteCommands { raw_cbs: SmallVec::new() } } /// Adds a command buffer to the list. @@ -1002,9 +1094,15 @@ pub struct UnsafeCommandBufferBuilderImageAspect { impl UnsafeCommandBufferBuilderImageAspect { pub(crate) fn to_vk_bits(&self) -> vk::ImageAspectFlagBits { let mut out = 0; - if self.color { out |= vk::IMAGE_ASPECT_COLOR_BIT }; - if self.depth { out |= vk::IMAGE_ASPECT_DEPTH_BIT }; - if self.stencil { out |= vk::IMAGE_ASPECT_STENCIL_BIT }; + if self.color { + out |= vk::IMAGE_ASPECT_COLOR_BIT + }; + if self.depth { + out |= vk::IMAGE_ASPECT_DEPTH_BIT + }; + if self.stencil { + out |= vk::IMAGE_ASPECT_STENCIL_BIT + }; out } } @@ -1072,8 +1170,10 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { self.dst_stage_mask |= other.dst_stage_mask; self.dependency_flags &= other.dependency_flags; - self.memory_barriers.extend(other.memory_barriers.into_iter()); - self.buffer_barriers.extend(other.buffer_barriers.into_iter()); + self.memory_barriers + .extend(other.memory_barriers.into_iter()); + self.buffer_barriers + .extend(other.buffer_barriers.into_iter()); self.image_barriers.extend(other.image_barriers.into_iter()); } @@ -1087,9 +1187,8 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { /// - There are certain rules regarding the pipeline barriers inside render passes. /// #[inline] - pub unsafe fn add_execution_dependency(&mut self, source: PipelineStages, dest: PipelineStages, - by_region: bool) - { + pub unsafe fn add_execution_dependency(&mut self, source: PipelineStages, + dest: PipelineStages, by_region: bool) { if !by_region { self.dependency_flags = 0; } @@ -1113,19 +1212,18 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { /// pub unsafe fn add_memory_barrier(&mut self, source_stage: PipelineStages, source_access: AccessFlagBits, dest_stage: PipelineStages, - dest_access: AccessFlagBits, by_region: bool) - { + dest_access: AccessFlagBits, by_region: bool) { debug_assert!(source_access.is_compatible_with(&source_stage)); debug_assert!(dest_access.is_compatible_with(&dest_stage)); self.add_execution_dependency(source_stage, dest_stage, by_region); self.memory_barriers.push(vk::MemoryBarrier { - sType: vk::STRUCTURE_TYPE_MEMORY_BARRIER, - pNext: ptr::null(), - srcAccessMask: source_access.into(), - dstAccessMask: dest_access.into(), - }); + sType: vk::STRUCTURE_TYPE_MEMORY_BARRIER, + pNext: ptr::null(), + srcAccessMask: source_access.into(), + dstAccessMask: dest_access.into(), + }); } /// Adds a buffer memory barrier. This means that all the memory writes to the given buffer by @@ -1143,11 +1241,12 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { /// is added. /// - Queue ownership transfers must be correct. /// - pub unsafe fn add_buffer_memory_barrier - (&mut self, buffer: &B, source_stage: PipelineStages, - source_access: AccessFlagBits, dest_stage: PipelineStages, - dest_access: AccessFlagBits, by_region: bool, - queue_transfer: Option<(u32, u32)>, offset: usize, size: usize) + pub unsafe fn add_buffer_memory_barrier(&mut self, buffer: &B, source_stage: PipelineStages, + source_access: AccessFlagBits, + dest_stage: PipelineStages, + dest_access: AccessFlagBits, by_region: bool, + queue_transfer: Option<(u32, u32)>, offset: usize, + size: usize) where B: ?Sized + BufferAccess { debug_assert!(source_access.is_compatible_with(&source_stage)); @@ -1156,7 +1255,10 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { self.add_execution_dependency(source_stage, dest_stage, by_region); debug_assert!(size <= buffer.size()); - let BufferInner { buffer, offset: org_offset } = buffer.inner(); + let BufferInner { + buffer, + offset: org_offset, + } = buffer.inner(); let offset = offset + org_offset; let (src_queue, dest_queue) = if let Some((src_queue, dest_queue)) = queue_transfer { @@ -1166,16 +1268,16 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { }; self.buffer_barriers.push(vk::BufferMemoryBarrier { - sType: vk::STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - pNext: ptr::null(), - srcAccessMask: source_access.into(), - dstAccessMask: dest_access.into(), - srcQueueFamilyIndex: src_queue, - dstQueueFamilyIndex: dest_queue, - buffer: buffer.internal_object(), - offset: offset as vk::DeviceSize, - size: size as vk::DeviceSize, - }); + sType: vk::STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + pNext: ptr::null(), + srcAccessMask: source_access.into(), + dstAccessMask: dest_access.into(), + srcQueueFamilyIndex: src_queue, + dstQueueFamilyIndex: dest_queue, + buffer: buffer.internal_object(), + offset: offset as vk::DeviceSize, + size: size as vk::DeviceSize, + }); } /// Adds an image memory barrier. This is the equivalent of `add_buffer_memory_barrier` but @@ -1196,10 +1298,12 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { /// - Access flags must be compatible with the image usage flags passed at image creation. /// pub unsafe fn add_image_memory_barrier(&mut self, image: &I, mipmaps: Range, - layers: Range, source_stage: PipelineStages, source_access: AccessFlagBits, - dest_stage: PipelineStages, dest_access: AccessFlagBits, by_region: bool, - queue_transfer: Option<(u32, u32)>, current_layout: ImageLayout, - new_layout: ImageLayout) + layers: Range, source_stage: PipelineStages, + source_access: AccessFlagBits, + dest_stage: PipelineStages, + dest_access: AccessFlagBits, by_region: bool, + queue_transfer: Option<(u32, u32)>, + current_layout: ImageLayout, new_layout: ImageLayout) where I: ?Sized + ImageAccess { debug_assert!(source_access.is_compatible_with(&source_stage)); @@ -1234,23 +1338,23 @@ impl UnsafeCommandBufferBuilderPipelineBarrier { }; self.image_barriers.push(vk::ImageMemoryBarrier { - sType: vk::STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - pNext: ptr::null(), - srcAccessMask: source_access.into(), - dstAccessMask: dest_access.into(), - oldLayout: current_layout as u32, - newLayout: new_layout as u32, - srcQueueFamilyIndex: src_queue, - dstQueueFamilyIndex: dest_queue, - image: image.inner().internal_object(), - subresourceRange: vk::ImageSubresourceRange { - aspectMask: aspect_mask, - baseMipLevel: mipmaps.start, - levelCount: mipmaps.end - mipmaps.start, - baseArrayLayer: layers.start, - layerCount: layers.end - layers.start, - }, - }); + sType: vk::STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + pNext: ptr::null(), + srcAccessMask: source_access.into(), + dstAccessMask: dest_access.into(), + oldLayout: current_layout as u32, + newLayout: new_layout as u32, + srcQueueFamilyIndex: src_queue, + dstQueueFamilyIndex: dest_queue, + image: image.inner().internal_object(), + subresourceRange: vk::ImageSubresourceRange { + aspectMask: aspect_mask, + baseMipLevel: mipmaps.start, + levelCount: mipmaps.end - mipmaps.start, + baseArrayLayer: layers.start, + layerCount: layers.end - layers.start, + }, + }); } } diff --git a/vulkano/src/command_buffer/traits.rs b/vulkano/src/command_buffer/traits.rs index 2771a0eb..b1051bf2 100644 --- a/vulkano/src/command_buffer/traits.rs +++ b/vulkano/src/command_buffer/traits.rs @@ -14,6 +14,8 @@ use std::sync::Mutex; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; +use SafeDeref; +use VulkanObject; use buffer::BufferAccess; use command_buffer::submit::SubmitAnyBuilder; use command_buffer::submit::SubmitCommandBufferBuilder; @@ -21,18 +23,16 @@ use command_buffer::sys::UnsafeCommandBuffer; use device::Device; use device::DeviceOwned; use device::Queue; -use image::ImageLayout; use image::ImageAccess; -use sync::now; -use sync::AccessError; +use image::ImageLayout; use sync::AccessCheckError; +use sync::AccessError; use sync::AccessFlagBits; use sync::FlushError; -use sync::NowFuture; use sync::GpuFuture; +use sync::NowFuture; use sync::PipelineStages; -use SafeDeref; -use VulkanObject; +use sync::now; pub unsafe trait CommandBuffer: DeviceOwned { /// The command pool of the command buffer. @@ -114,9 +114,11 @@ pub unsafe trait CommandBuffer: DeviceOwned { #[inline] fn execute_after(self, future: F, queue: Arc) -> Result, CommandBufferExecError> - where Self: Sized + 'static, F: GpuFuture + where Self: Sized + 'static, + F: GpuFuture { - assert_eq!(self.device().internal_object(), future.device().internal_object()); + assert_eq!(self.device().internal_object(), + future.device().internal_object()); self.prepare_submit(&future, &queue)?; @@ -125,18 +127,19 @@ pub unsafe trait CommandBuffer: DeviceOwned { } Ok(CommandBufferExecFuture { - previous: future, - command_buffer: self, - queue: queue, - submitted: Mutex::new(false), - finished: AtomicBool::new(false), - }) + previous: future, + command_buffer: self, + queue: queue, + submitted: Mutex::new(false), + finished: AtomicBool::new(false), + }) } fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) -> Result, AccessCheckError>; - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) -> Result, AccessCheckError>; // FIXME: lots of other methods @@ -153,7 +156,10 @@ pub unsafe trait CommandBufferBuild { fn build(self) -> Result; } -unsafe impl CommandBuffer for T where T: SafeDeref, T::Target: CommandBuffer { +unsafe impl CommandBuffer for T + where T: SafeDeref, + T::Target: CommandBuffer +{ type PoolAlloc = ::PoolAlloc; #[inline] @@ -162,21 +168,22 @@ unsafe impl CommandBuffer for T where T: SafeDeref, T::Target: CommandBuffer } #[inline] - fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> { + fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) + -> Result<(), CommandBufferExecError> { (**self).prepare_submit(future, queue) } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { (**self).check_buffer_access(buffer, exclusive, queue) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { (**self).check_image_access(image, layout, exclusive, queue) } } @@ -184,7 +191,10 @@ unsafe impl CommandBuffer for T where T: SafeDeref, T::Target: CommandBuffer /// Represents a command buffer being executed by the GPU and the moment when the execution /// finishes. #[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"] -pub struct CommandBufferExecFuture where F: GpuFuture, Cb: CommandBuffer { +pub struct CommandBufferExecFuture + where F: GpuFuture, + Cb: CommandBuffer +{ previous: F, command_buffer: Cb, queue: Arc, @@ -196,7 +206,8 @@ pub struct CommandBufferExecFuture where F: GpuFuture, Cb: CommandBuffer } unsafe impl GpuFuture for CommandBufferExecFuture - where F: GpuFuture, Cb: CommandBuffer + where F: GpuFuture, + Cb: CommandBuffer { #[inline] fn cleanup_finished(&mut self) { @@ -204,30 +215,31 @@ unsafe impl GpuFuture for CommandBufferExecFuture } unsafe fn build_submission(&self) -> Result { - Ok(match try!(self.previous.build_submission()) { - SubmitAnyBuilder::Empty => { - let mut builder = SubmitCommandBufferBuilder::new(); - builder.add_command_buffer(self.command_buffer.inner()); - SubmitAnyBuilder::CommandBuffer(builder) - }, - SubmitAnyBuilder::SemaphoresWait(sem) => { - let mut builder: SubmitCommandBufferBuilder = sem.into(); - builder.add_command_buffer(self.command_buffer.inner()); - SubmitAnyBuilder::CommandBuffer(builder) - }, - SubmitAnyBuilder::CommandBuffer(mut builder) => { - // FIXME: add pipeline barrier - builder.add_command_buffer(self.command_buffer.inner()); - SubmitAnyBuilder::CommandBuffer(builder) - }, - SubmitAnyBuilder::QueuePresent(_) | SubmitAnyBuilder::BindSparse(_) => { - unimplemented!() // TODO: + Ok(match self.previous.build_submission()? { + SubmitAnyBuilder::Empty => { + let mut builder = SubmitCommandBufferBuilder::new(); + builder.add_command_buffer(self.command_buffer.inner()); + SubmitAnyBuilder::CommandBuffer(builder) + }, + SubmitAnyBuilder::SemaphoresWait(sem) => { + let mut builder: SubmitCommandBufferBuilder = sem.into(); + builder.add_command_buffer(self.command_buffer.inner()); + SubmitAnyBuilder::CommandBuffer(builder) + }, + SubmitAnyBuilder::CommandBuffer(mut builder) => { + // FIXME: add pipeline barrier + builder.add_command_buffer(self.command_buffer.inner()); + SubmitAnyBuilder::CommandBuffer(builder) + }, + SubmitAnyBuilder::QueuePresent(_) | + SubmitAnyBuilder::BindSparse(_) => { + unimplemented!() // TODO: /*present.submit(); // TODO: wrong let mut builder = SubmitCommandBufferBuilder::new(); builder.add_command_buffer(self.command_buffer.inner()); SubmitAnyBuilder::CommandBuffer(builder)*/ - }, - }) + }, + }) } #[inline] @@ -240,10 +252,10 @@ unsafe impl GpuFuture for CommandBufferExecFuture let queue = self.queue.clone(); - match try!(self.build_submission()) { + match self.build_submission()? { SubmitAnyBuilder::Empty => {}, SubmitAnyBuilder::CommandBuffer(builder) => { - try!(builder.submit(&queue)); + builder.submit(&queue)?; }, _ => unreachable!(), }; @@ -271,10 +283,11 @@ unsafe impl GpuFuture for CommandBufferExecFuture } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - match self.command_buffer.check_buffer_access(buffer, exclusive, queue) { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { + match self.command_buffer + .check_buffer_access(buffer, exclusive, queue) { Ok(v) => Ok(v), Err(AccessCheckError::Denied(err)) => Err(AccessCheckError::Denied(err)), Err(AccessCheckError::Unknown) => { @@ -284,21 +297,24 @@ unsafe impl GpuFuture for CommandBufferExecFuture } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - match self.command_buffer.check_image_access(image, layout, exclusive, queue) { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { + match self.command_buffer + .check_image_access(image, layout, exclusive, queue) { Ok(v) => Ok(v), Err(AccessCheckError::Denied(err)) => Err(AccessCheckError::Denied(err)), Err(AccessCheckError::Unknown) => { - self.previous.check_image_access(image, layout, exclusive, queue) + self.previous + .check_image_access(image, layout, exclusive, queue) }, } } } unsafe impl DeviceOwned for CommandBufferExecFuture - where F: GpuFuture, Cb: CommandBuffer + where F: GpuFuture, + Cb: CommandBuffer { #[inline] fn device(&self) -> &Arc { @@ -306,7 +322,10 @@ unsafe impl DeviceOwned for CommandBufferExecFuture } } -impl Drop for CommandBufferExecFuture where F: GpuFuture, Cb: CommandBuffer { +impl Drop for CommandBufferExecFuture + where F: GpuFuture, + Cb: CommandBuffer +{ fn drop(&mut self) { unsafe { if !*self.finished.get_mut() { diff --git a/vulkano/src/command_buffer/validity/copy_buffer.rs b/vulkano/src/command_buffer/validity/copy_buffer.rs index 23d2b0b9..e117c9f5 100644 --- a/vulkano/src/command_buffer/validity/copy_buffer.rs +++ b/vulkano/src/command_buffer/validity/copy_buffer.rs @@ -11,10 +11,10 @@ use std::cmp; use std::error; use std::fmt; +use VulkanObject; use buffer::BufferAccess; use device::Device; use device::DeviceOwned; -use VulkanObject; /// Checks whether a copy buffer command is valid. /// @@ -28,8 +28,10 @@ pub fn check_copy_buffer(device: &Device, source: &S, destination: &D) where S: ?Sized + BufferAccess, D: ?Sized + BufferAccess { - assert_eq!(source.inner().buffer.device().internal_object(), device.internal_object()); - assert_eq!(destination.inner().buffer.device().internal_object(), device.internal_object()); + assert_eq!(source.inner().buffer.device().internal_object(), + device.internal_object()); + assert_eq!(destination.inner().buffer.device().internal_object(), + device.internal_object()); if !source.inner().buffer.usage_transfer_src() { return Err(CheckCopyBufferError::SourceMissingTransferUsage); diff --git a/vulkano/src/command_buffer/validity/fill_buffer.rs b/vulkano/src/command_buffer/validity/fill_buffer.rs index 519aa5c5..ea2bd0d6 100644 --- a/vulkano/src/command_buffer/validity/fill_buffer.rs +++ b/vulkano/src/command_buffer/validity/fill_buffer.rs @@ -10,10 +10,10 @@ use std::error; use std::fmt; +use VulkanObject; use buffer::BufferAccess; use device::Device; use device::DeviceOwned; -use VulkanObject; /// Checks whether a fill buffer command is valid. /// @@ -24,7 +24,8 @@ use VulkanObject; pub fn check_fill_buffer(device: &Device, buffer: &B) -> Result<(), CheckFillBufferError> where B: ?Sized + BufferAccess { - assert_eq!(buffer.inner().buffer.device().internal_object(), device.internal_object()); + assert_eq!(buffer.inner().buffer.device().internal_object(), + device.internal_object()); if !buffer.inner().buffer.usage_transfer_dest() { return Err(CheckFillBufferError::BufferMissingUsage); diff --git a/vulkano/src/command_buffer/validity/mod.rs b/vulkano/src/command_buffer/validity/mod.rs index fa0b3d2f..19686a46 100644 --- a/vulkano/src/command_buffer/validity/mod.rs +++ b/vulkano/src/command_buffer/validity/mod.rs @@ -9,10 +9,10 @@ //! Functions that check the validity of commands. -pub use self::copy_buffer::{check_copy_buffer, CheckCopyBufferError}; -pub use self::dynamic_state::{check_dynamic_state_validity, CheckDynamicStateValidityError}; -pub use self::fill_buffer::{check_fill_buffer, CheckFillBufferError}; -pub use self::update_buffer::{check_update_buffer, CheckUpdateBufferError}; +pub use self::copy_buffer::{CheckCopyBufferError, check_copy_buffer}; +pub use self::dynamic_state::{CheckDynamicStateValidityError, check_dynamic_state_validity}; +pub use self::fill_buffer::{CheckFillBufferError, check_fill_buffer}; +pub use self::update_buffer::{CheckUpdateBufferError, check_update_buffer}; mod copy_buffer; mod dynamic_state; diff --git a/vulkano/src/command_buffer/validity/update_buffer.rs b/vulkano/src/command_buffer/validity/update_buffer.rs index 5a1bfad2..dae2e6e3 100644 --- a/vulkano/src/command_buffer/validity/update_buffer.rs +++ b/vulkano/src/command_buffer/validity/update_buffer.rs @@ -12,10 +12,10 @@ use std::error; use std::fmt; use std::mem; +use VulkanObject; use buffer::BufferAccess; use device::Device; use device::DeviceOwned; -use VulkanObject; /// Checks whether an update buffer command is valid. /// @@ -28,7 +28,8 @@ pub fn check_update_buffer(device: &Device, buffer: &B, data: &D) where B: ?Sized + BufferAccess, D: ?Sized { - assert_eq!(buffer.inner().buffer.device().internal_object(), device.internal_object()); + assert_eq!(buffer.inner().buffer.device().internal_object(), + device.internal_object()); if !buffer.inner().buffer.usage_transfer_dest() { return Err(CheckUpdateBufferError::BufferMissingUsage); diff --git a/vulkano/src/descriptor/descriptor.rs b/vulkano/src/descriptor/descriptor.rs index 5f65e596..25c43693 100644 --- a/vulkano/src/descriptor/descriptor.rs +++ b/vulkano/src/descriptor/descriptor.rs @@ -8,14 +8,14 @@ // according to those terms. //! Description of a single descriptor. -//! +//! //! This module contains traits and structs related to describing a single descriptor. A descriptor //! is a slot where you can bind a buffer or an image so that it can be accessed from your shaders. //! In order to specify which buffer or image to bind to a descriptor, see the `descriptor_set` //! module. -//! +//! //! There are four different kinds of descriptors that give access to buffers: -//! +//! //! - Uniform texel buffers. Gives read-only access to the content of a buffer. Only supports //! certain buffer formats. //! - Storage texel buffers. Gives read and/or write access to the content of a buffer. Only @@ -25,9 +25,9 @@ //! sometimes slower than uniform texel buffers. //! - Storage buffers. Gives read and/or write access to the content of a buffer. Less restrictive //! but sometimes slower than uniform buffers and storage texel buffers. -//! +//! //! There are five different kinds of descriptors related to images: -//! +//! //! - Storage images. Gives read and/or write access to individual pixels in an image. The image //! cannot be sampled. In other words, you have exactly specify which pixel to read or write. //! - Sampled images. Gives read-only access to an image. Before you can use a sampled image in a @@ -36,14 +36,14 @@ //! - Samplers. Doesn't contain an image but a sampler object that describes how an image will be //! accessed. This is meant to be combined with a sampled image (see above). //! - Combined image and sampler. Similar to a sampled image, but also directly includes the -//! sampler which indicates how the sampling is done. +//! sampler which indicates how the sampling is done. //! - Input attachments. The fastest but also most restrictive access to images. Must be integrated //! in a render pass. Can only give access to the same pixel as the one you're processing. -//! +//! +use format::Format; use std::cmp; use std::ops::BitOr; -use format::Format; use vk; /// Contains the exact description of a single descriptor. @@ -77,9 +77,8 @@ impl DescriptorDesc { // TODO: return Result instead of bool #[inline] pub fn is_superset_of(&self, other: &DescriptorDesc) -> bool { - self.ty.is_superset_of(&other.ty) && - self.array_count >= other.array_count && self.stages.is_superset_of(&other.stages) && - (!self.readonly || other.readonly) + self.ty.is_superset_of(&other.ty) && self.array_count >= other.array_count && + self.stages.is_superset_of(&other.stages) && (!self.readonly || other.readonly) } /// Builds a `DescriptorDesc` that is the union of `self` and `other`, if possible. @@ -89,22 +88,24 @@ impl DescriptorDesc { // TODO: add example #[inline] pub fn union(&self, other: &DescriptorDesc) -> Option { - if self.ty != other.ty { return None; } + if self.ty != other.ty { + return None; + } Some(DescriptorDesc { - ty: self.ty.clone(), - array_count: cmp::max(self.array_count, other.array_count), - stages: self.stages | other.stages, - readonly: self.readonly && other.readonly, - }) + ty: self.ty.clone(), + array_count: cmp::max(self.array_count, other.array_count), + stages: self.stages | other.stages, + readonly: self.readonly && other.readonly, + }) } } /// Describes the content and layout of each array element of a descriptor. #[derive(Debug, Clone, PartialEq, Eq)] pub enum DescriptorDescTy { - Sampler, // TODO: the sampler has some restrictions as well - CombinedImageSampler(DescriptorImageDesc), // TODO: the sampler has some restrictions as well + Sampler, // TODO: the sampler has some restrictions as well + CombinedImageSampler(DescriptorImageDesc), // TODO: the sampler has some restrictions as well Image(DescriptorImageDesc), TexelBuffer { /// If `true`, this describes a storage texel buffer. @@ -131,27 +132,36 @@ impl DescriptorDescTy { // TODO: add example pub fn ty(&self) -> Option { Some(match *self { - DescriptorDescTy::Sampler => DescriptorType::Sampler, - DescriptorDescTy::CombinedImageSampler(_) => DescriptorType::CombinedImageSampler, - DescriptorDescTy::Image(ref desc) => { - if desc.sampled { DescriptorType::SampledImage } - else { DescriptorType::StorageImage } - }, - DescriptorDescTy::InputAttachment { .. } => DescriptorType::InputAttachment, - DescriptorDescTy::Buffer(ref desc) => { - let dynamic = match desc.dynamic { Some(d) => d, None => return None }; - match (desc.storage, dynamic) { - (false, false) => DescriptorType::UniformBuffer, - (true, false) => DescriptorType::StorageBuffer, - (false, true) => DescriptorType::UniformBufferDynamic, - (true, true) => DescriptorType::StorageBufferDynamic, - } - }, - DescriptorDescTy::TexelBuffer { storage, .. } => { - if storage { DescriptorType::StorageTexelBuffer } - else { DescriptorType::UniformTexelBuffer } - }, - }) + DescriptorDescTy::Sampler => DescriptorType::Sampler, + DescriptorDescTy::CombinedImageSampler(_) => DescriptorType::CombinedImageSampler, + DescriptorDescTy::Image(ref desc) => { + if desc.sampled { + DescriptorType::SampledImage + } else { + DescriptorType::StorageImage + } + }, + DescriptorDescTy::InputAttachment { .. } => DescriptorType::InputAttachment, + DescriptorDescTy::Buffer(ref desc) => { + let dynamic = match desc.dynamic { + Some(d) => d, + None => return None, + }; + match (desc.storage, dynamic) { + (false, false) => DescriptorType::UniformBuffer, + (true, false) => DescriptorType::StorageBuffer, + (false, true) => DescriptorType::UniformBufferDynamic, + (true, true) => DescriptorType::StorageBufferDynamic, + } + }, + DescriptorDescTy::TexelBuffer { storage, .. } => { + if storage { + DescriptorType::StorageTexelBuffer + } else { + DescriptorType::UniformTexelBuffer + } + }, + }) } /// Checks whether we are a superset of another descriptor type. @@ -164,14 +174,17 @@ impl DescriptorDescTy { (&DescriptorDescTy::CombinedImageSampler(ref me), &DescriptorDescTy::CombinedImageSampler(ref other)) => me.is_superset_of(other), - (&DescriptorDescTy::Image(ref me), - &DescriptorDescTy::Image(ref other)) => me.is_superset_of(other), + (&DescriptorDescTy::Image(ref me), &DescriptorDescTy::Image(ref other)) => + me.is_superset_of(other), - (&DescriptorDescTy::InputAttachment { multisampled: me_multisampled, - array_layers: me_array_layers }, - &DescriptorDescTy::InputAttachment { multisampled: other_multisampled, - array_layers: other_array_layers }) => - { + (&DescriptorDescTy::InputAttachment { + multisampled: me_multisampled, + array_layers: me_array_layers, + }, + &DescriptorDescTy::InputAttachment { + multisampled: other_multisampled, + array_layers: other_array_layers, + }) => { me_multisampled == other_multisampled && me_array_layers == other_array_layers }, @@ -188,9 +201,14 @@ impl DescriptorDescTy { } }, - (&DescriptorDescTy::TexelBuffer { storage: me_storage, format: me_format }, - &DescriptorDescTy::TexelBuffer { storage: other_storage, format: other_format }) => - { + (&DescriptorDescTy::TexelBuffer { + storage: me_storage, + format: me_format, + }, + &DescriptorDescTy::TexelBuffer { + storage: other_storage, + format: other_format, + }) => { if me_storage != other_storage { return false; } @@ -204,7 +222,7 @@ impl DescriptorDescTy { }, // Any other combination is invalid. - _ => false + _ => false, } } } @@ -240,7 +258,9 @@ impl DescriptorImageDesc { } match (self.format, other.format) { - (Some(a), Some(b)) => if a != b { return false; }, + (Some(a), Some(b)) => if a != b { + return false; + }, (Some(_), None) => (), (None, None) => (), (None, Some(_)) => return false, @@ -249,16 +269,17 @@ impl DescriptorImageDesc { match (self.array_layers, other.array_layers) { (DescriptorImageDescArray::NonArrayed, DescriptorImageDescArray::NonArrayed) => (), (DescriptorImageDescArray::Arrayed { max_layers: my_max }, - DescriptorImageDescArray::Arrayed { max_layers: other_max }) => - { + DescriptorImageDescArray::Arrayed { max_layers: other_max }) => { match (my_max, other_max) { - (Some(m), Some(o)) => if m < o { return false; }, + (Some(m), Some(o)) => if m < o { + return false; + }, (Some(_), None) => (), (None, Some(_)) => return false, (None, None) => (), // TODO: is this correct? }; }, - _ => return false + _ => return false, }; true @@ -269,7 +290,7 @@ impl DescriptorImageDesc { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DescriptorImageDescArray { NonArrayed, - Arrayed { max_layers: Option } + Arrayed { max_layers: Option }, } // TODO: documentation @@ -294,11 +315,10 @@ pub struct DescriptorBufferDesc { pub enum DescriptorBufferContentDesc { F32, F64, - Struct { - - }, + Struct {}, Array { - len: Box, num_array: usize + len: Box, + num_array: usize, }, } @@ -401,11 +421,10 @@ impl ShaderStages { #[inline] pub fn is_superset_of(&self, other: &ShaderStages) -> bool { (self.vertex || !other.vertex) && - (self.tessellation_control || !other.tessellation_control) && - (self.tessellation_evaluation || !other.tessellation_evaluation) && - (self.geometry || !other.geometry) && - (self.fragment || !other.fragment) && - (self.compute || !other.compute) + (self.tessellation_control || !other.tessellation_control) && + (self.tessellation_evaluation || !other.tessellation_evaluation) && + (self.geometry || !other.geometry) && (self.fragment || !other.fragment) && + (self.compute || !other.compute) } /// Checks whether any of the stages in `self` are also present in `other`. @@ -413,11 +432,10 @@ impl ShaderStages { #[inline] pub fn intersects(&self, other: &ShaderStages) -> bool { (self.vertex && other.vertex) || - (self.tessellation_control && other.tessellation_control) || - (self.tessellation_evaluation && other.tessellation_evaluation) || - (self.geometry && other.geometry) || - (self.fragment && other.fragment) || - (self.compute && other.compute) + (self.tessellation_control && other.tessellation_control) || + (self.tessellation_evaluation && other.tessellation_evaluation) || + (self.geometry && other.geometry) || (self.fragment && other.fragment) || + (self.compute && other.compute) } } @@ -442,12 +460,24 @@ impl Into for ShaderStages { #[inline] fn into(self) -> vk::ShaderStageFlags { let mut result = 0; - if self.vertex { result |= vk::SHADER_STAGE_VERTEX_BIT; } - if self.tessellation_control { result |= vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT; } - if self.tessellation_evaluation { result |= vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT; } - if self.geometry { result |= vk::SHADER_STAGE_GEOMETRY_BIT; } - if self.fragment { result |= vk::SHADER_STAGE_FRAGMENT_BIT; } - if self.compute { result |= vk::SHADER_STAGE_COMPUTE_BIT; } + if self.vertex { + result |= vk::SHADER_STAGE_VERTEX_BIT; + } + if self.tessellation_control { + result |= vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT; + } + if self.tessellation_evaluation { + result |= vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + } + if self.geometry { + result |= vk::SHADER_STAGE_GEOMETRY_BIT; + } + if self.fragment { + result |= vk::SHADER_STAGE_FRAGMENT_BIT; + } + if self.compute { + result |= vk::SHADER_STAGE_COMPUTE_BIT; + } result } } diff --git a/vulkano/src/descriptor/descriptor_set/collection.rs b/vulkano/src/descriptor/descriptor_set/collection.rs index 97f87f67..a2d00acd 100644 --- a/vulkano/src/descriptor/descriptor_set/collection.rs +++ b/vulkano/src/descriptor/descriptor_set/collection.rs @@ -7,12 +7,12 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::iter; use buffer::BufferAccess; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor_set::DescriptorSet; use descriptor::descriptor_set::DescriptorSetDesc; use image::ImageAccess; +use std::iter; /// A collection of descriptor set objects. pub unsafe trait DescriptorSetsCollection { @@ -74,7 +74,7 @@ unsafe impl DescriptorSetsCollection for T fn num_bindings_in_set(&self, set: usize) -> Option { match set { 0 => Some(self.num_bindings()), - _ => None + _ => None, } } @@ -82,7 +82,7 @@ unsafe impl DescriptorSetsCollection for T fn descriptor(&self, set: usize, binding: usize) -> Option { match set { 0 => self.descriptor(binding), - _ => None + _ => None, } } @@ -185,4 +185,29 @@ macro_rules! impl_collection { ($i:ident) => (); } -impl_collection!(Z, Y, X, W, V, U, T, S, R, Q, P, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A); +impl_collection!(Z, + Y, + X, + W, + V, + U, + T, + S, + R, + Q, + P, + O, + N, + M, + L, + K, + J, + I, + H, + G, + F, + E, + D, + C, + B, + A); diff --git a/vulkano/src/descriptor/descriptor_set/mod.rs b/vulkano/src/descriptor/descriptor_set/mod.rs index c30df149..692214db 100644 --- a/vulkano/src/descriptor/descriptor_set/mod.rs +++ b/vulkano/src/descriptor/descriptor_set/mod.rs @@ -8,10 +8,10 @@ // according to those terms. //! Descriptor sets creation and management -//! +//! //! This module is dedicated to managing descriptor sets. There are three concepts in Vulkan //! related to descriptor sets: -//! +//! //! - A `DescriptorSetLayout` is a Vulkan object that describes to the Vulkan implementation the //! layout of a future descriptor set. When you allocate a descriptor set, you have to pass an //! instance of this object. This is represented with the `UnsafeDescriptorSetLayout` type in @@ -21,9 +21,9 @@ //! `UnsafeDescriptorPool` type in vulkano. //! - A `DescriptorSet` contains the bindings to resources and is allocated from a pool. This is //! represented with the `UnsafeDescriptorSet` type in vulkano. -//! +//! //! In addition to this, vulkano defines the following: -//! +//! //! - The `DescriptorPool` trait can be implemented on types from which you can allocate and free //! descriptor sets. However it is different from Vulkan descriptor pools in the sense that an //! implementation of the `DescriptorPool` trait can manage multiple Vulkan descriptor pools. @@ -35,15 +35,15 @@ //! - The `DescriptorSetsCollection` trait is implemented on collections of types that implement //! `DescriptorSet`. It is what you pass to the draw functions. +use SafeDeref; use buffer::BufferAccess; use descriptor::descriptor::DescriptorDesc; use image::ImageAccess; -use SafeDeref; pub use self::collection::DescriptorSetsCollection; +pub use self::simple::*; pub use self::std_pool::StdDescriptorPool; pub use self::std_pool::StdDescriptorPoolAlloc; -pub use self::simple::*; pub use self::sys::DescriptorPool; pub use self::sys::DescriptorPoolAlloc; pub use self::sys::DescriptorPoolAllocError; @@ -77,7 +77,10 @@ pub unsafe trait DescriptorSet: DescriptorSetDesc { fn images_list<'a>(&'a self) -> Box + 'a>; } -unsafe impl DescriptorSet for T where T: SafeDeref, T::Target: DescriptorSet { +unsafe impl DescriptorSet for T + where T: SafeDeref, + T::Target: DescriptorSet +{ #[inline] fn inner(&self) -> &UnsafeDescriptorSet { (**self).inner() @@ -103,7 +106,10 @@ pub unsafe trait DescriptorSetDesc { fn descriptor(&self, binding: usize) -> Option; } -unsafe impl DescriptorSetDesc for T where T: SafeDeref, T::Target: DescriptorSetDesc { +unsafe impl DescriptorSetDesc for T + where T: SafeDeref, + T::Target: DescriptorSetDesc +{ #[inline] fn num_bindings(&self) -> usize { (**self).num_bindings() diff --git a/vulkano/src/descriptor/descriptor_set/simple.rs b/vulkano/src/descriptor/descriptor_set/simple.rs index bf947d96..5170d8b9 100644 --- a/vulkano/src/descriptor/descriptor_set/simple.rs +++ b/vulkano/src/descriptor/descriptor_set/simple.rs @@ -1,98 +1,106 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. -use std::sync::Arc; +use std::sync::Arc; -use buffer::BufferAccess; -use buffer::BufferViewRef; -use descriptor::descriptor::DescriptorDesc; -use descriptor::descriptor::DescriptorType; -use descriptor::descriptor_set::DescriptorSet; -use descriptor::descriptor_set::DescriptorSetDesc; -use descriptor::descriptor_set::UnsafeDescriptorSetLayout; -use descriptor::descriptor_set::DescriptorPool; -use descriptor::descriptor_set::DescriptorPoolAlloc; -use descriptor::descriptor_set::UnsafeDescriptorSet; -use descriptor::descriptor_set::DescriptorWrite; -use descriptor::descriptor_set::StdDescriptorPool; -use descriptor::pipeline_layout::PipelineLayoutAbstract; -use device::Device; -use device::DeviceOwned; -use image::ImageAccess; -use image::ImageLayout; -use image::ImageViewAccess; -use sampler::Sampler; -use sync::AccessFlagBits; -use sync::PipelineStages; - -/// A simple immutable descriptor set. -/// -/// It is named "simple" because creating such a descriptor set allocates from a pool, and because -/// it can't be modified once created. It is sufficient for most usages, but in some situations -/// you may wish to use something more optimized instead. -/// -/// In order to build a `SimpleDescriptorSet`, you need to use a `SimpleDescriptorSetBuilder`. But -/// the easiest way is to use the `simple_descriptor_set!` macro. -/// -/// The template parameter of the `SimpleDescriptorSet` is very complex, and you shouldn't try to -/// express it explicitely. If you want to store your descriptor set in a struct or in a `Vec` for -/// example, you are encouraged to turn `SimpleDescriptorSet` into a `Box` or a -/// `Arc`. -/// -/// # Example -// TODO: -pub struct SimpleDescriptorSet> where P: DescriptorPool { - inner: P::Alloc, - resources: R, - layout: Arc -} - -impl SimpleDescriptorSet where P: DescriptorPool { - /// Returns the layout used to create this descriptor set. - #[inline] - pub fn set_layout(&self) -> &Arc { - &self.layout - } -} - -unsafe impl DescriptorSet for SimpleDescriptorSet where P: DescriptorPool { - #[inline] - fn inner(&self) -> &UnsafeDescriptorSet { - self.inner.inner() - } - - #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() - } - - #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() - } -} - -unsafe impl DescriptorSetDesc for SimpleDescriptorSet where P: DescriptorPool { - #[inline] - fn num_bindings(&self) -> usize { - unimplemented!() // FIXME: - } - - #[inline] - fn descriptor(&self, binding: usize) -> Option { - unimplemented!() // FIXME: - } -} - -/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object. -// TODO: more doc -#[macro_export] +use buffer::BufferAccess; +use buffer::BufferViewRef; +use descriptor::descriptor::DescriptorDesc; +use descriptor::descriptor::DescriptorType; +use descriptor::descriptor_set::DescriptorPool; +use descriptor::descriptor_set::DescriptorPoolAlloc; +use descriptor::descriptor_set::DescriptorSet; +use descriptor::descriptor_set::DescriptorSetDesc; +use descriptor::descriptor_set::DescriptorWrite; +use descriptor::descriptor_set::StdDescriptorPool; +use descriptor::descriptor_set::UnsafeDescriptorSet; +use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use descriptor::pipeline_layout::PipelineLayoutAbstract; +use device::Device; +use device::DeviceOwned; +use image::ImageAccess; +use image::ImageLayout; +use image::ImageViewAccess; +use sampler::Sampler; +use sync::AccessFlagBits; +use sync::PipelineStages; + +/// A simple immutable descriptor set. +/// +/// It is named "simple" because creating such a descriptor set allocates from a pool, and because +/// it can't be modified once created. It is sufficient for most usages, but in some situations +/// you may wish to use something more optimized instead. +/// +/// In order to build a `SimpleDescriptorSet`, you need to use a `SimpleDescriptorSetBuilder`. But +/// the easiest way is to use the `simple_descriptor_set!` macro. +/// +/// The template parameter of the `SimpleDescriptorSet` is very complex, and you shouldn't try to +/// express it explicitely. If you want to store your descriptor set in a struct or in a `Vec` for +/// example, you are encouraged to turn `SimpleDescriptorSet` into a `Box` or a +/// `Arc`. +/// +/// # Example +// TODO: +pub struct SimpleDescriptorSet> + where P: DescriptorPool +{ + inner: P::Alloc, + resources: R, + layout: Arc, +} + +impl SimpleDescriptorSet + where P: DescriptorPool +{ + /// Returns the layout used to create this descriptor set. + #[inline] + pub fn set_layout(&self) -> &Arc { + &self.layout + } +} + +unsafe impl DescriptorSet for SimpleDescriptorSet + where P: DescriptorPool +{ + #[inline] + fn inner(&self) -> &UnsafeDescriptorSet { + self.inner.inner() + } + + #[inline] + fn buffers_list<'a>(&'a self) -> Box + 'a> { + unimplemented!() + } + + #[inline] + fn images_list<'a>(&'a self) -> Box + 'a> { + unimplemented!() + } +} + +unsafe impl DescriptorSetDesc for SimpleDescriptorSet + where P: DescriptorPool +{ + #[inline] + fn num_bindings(&self) -> usize { + unimplemented!() // FIXME: + } + + #[inline] + fn descriptor(&self, binding: usize) -> Option { + unimplemented!() // FIXME: + } +} + +/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object. +// TODO: more doc +#[macro_export] macro_rules! simple_descriptor_set { ($layout:expr, $set_num:expr, {$($name:ident: $val:expr),*$(,)*}) => ({ #[allow(unused_imports)] @@ -122,267 +130,283 @@ macro_rules! simple_descriptor_set { builder.build() }); -} - -/// Prototype of a `SimpleDescriptorSet`. -/// -/// > **Note**: You are encouraged to use the `simple_descriptor_set!` macro instead of -/// > manipulating these internals. -/// -/// The template parameter `L` is the pipeline layout to use, and the template parameter `R` is -/// a complex unspecified type that represents the list of resources. -/// -/// # Example -// TODO: example here -pub struct SimpleDescriptorSetBuilder { - // The pipeline layout. - layout: L, - // Id of the set within the pipeline layout. - set_id: usize, - // The writes to perform on a descriptor set in order to put the resources in it. - writes: Vec, - // Holds the resources alive. - resources: R, -} - -impl SimpleDescriptorSetBuilder where L: PipelineLayoutAbstract { - /// Builds a new prototype for a `SimpleDescriptorSet`. Requires a reference to a pipeline - /// layout, and the id of the set within the layout. - /// - /// # Panic - /// - /// - Panics if the set id is out of range. - /// - pub fn new(layout: L, set_id: usize) -> SimpleDescriptorSetBuilder { - assert!(layout.num_sets() > set_id); - - let cap = layout.num_bindings_in_set(set_id).unwrap_or(0); - - SimpleDescriptorSetBuilder { - layout: layout, - set_id: set_id, - writes: Vec::with_capacity(cap), - resources: (), - } - } -} - -impl SimpleDescriptorSetBuilder where L: PipelineLayoutAbstract { - /// Builds a `SimpleDescriptorSet` from the builder. - pub fn build(self) -> SimpleDescriptorSet> { - // TODO: check that we filled everything - let pool = Device::standard_descriptor_pool(self.layout.device()); - let set_layout = self.layout.descriptor_set_layout(self.set_id).unwrap().clone(); // FIXME: error - - let set = unsafe { - let mut set = pool.alloc(&set_layout).unwrap(); // FIXME: error - set.inner_mut().write(pool.device(), self.writes.into_iter()); - set - }; - - SimpleDescriptorSet { - inner: set, - resources: self.resources, - layout: set_layout, - } - } -} - -/// Trait implemented on buffers so that they can be appended to a simple descriptor set builder. -pub unsafe trait SimpleDescriptorSetBufferExt { - /// The new type of the template parameter `R` of the builder. - type Out; - - /// Appends the buffer to the `SimpleDescriptorSetBuilder`. - // TODO: return Result - fn add_me(self, i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder; -} - -unsafe impl SimpleDescriptorSetBufferExt for T - where T: BufferAccess, L: PipelineLayoutAbstract -{ - type Out = (R, SimpleDescriptorSetBuf); - - fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder - { - let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead - assert_eq!(set_id, i.set_id); // TODO: Result instead - let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead - - assert!(desc.array_count == 1); // not implemented +} + +/// Prototype of a `SimpleDescriptorSet`. +/// +/// > **Note**: You are encouraged to use the `simple_descriptor_set!` macro instead of +/// > manipulating these internals. +/// +/// The template parameter `L` is the pipeline layout to use, and the template parameter `R` is +/// a complex unspecified type that represents the list of resources. +/// +/// # Example +// TODO: example here +pub struct SimpleDescriptorSetBuilder { + // The pipeline layout. + layout: L, + // Id of the set within the pipeline layout. + set_id: usize, + // The writes to perform on a descriptor set in order to put the resources in it. + writes: Vec, + // Holds the resources alive. + resources: R, +} + +impl SimpleDescriptorSetBuilder + where L: PipelineLayoutAbstract +{ + /// Builds a new prototype for a `SimpleDescriptorSet`. Requires a reference to a pipeline + /// layout, and the id of the set within the layout. + /// + /// # Panic + /// + /// - Panics if the set id is out of range. + /// + pub fn new(layout: L, set_id: usize) -> SimpleDescriptorSetBuilder { + assert!(layout.num_sets() > set_id); + + let cap = layout.num_bindings_in_set(set_id).unwrap_or(0); + + SimpleDescriptorSetBuilder { + layout: layout, + set_id: set_id, + writes: Vec::with_capacity(cap), + resources: (), + } + } +} + +impl SimpleDescriptorSetBuilder + where L: PipelineLayoutAbstract +{ + /// Builds a `SimpleDescriptorSet` from the builder. + pub fn build(self) -> SimpleDescriptorSet> { + // TODO: check that we filled everything + let pool = Device::standard_descriptor_pool(self.layout.device()); + let set_layout = self.layout + .descriptor_set_layout(self.set_id) + .unwrap() + .clone(); // FIXME: error + + let set = unsafe { + let mut set = pool.alloc(&set_layout).unwrap(); // FIXME: error + set.inner_mut() + .write(pool.device(), self.writes.into_iter()); + set + }; + + SimpleDescriptorSet { + inner: set, + resources: self.resources, + layout: set_layout, + } + } +} + +/// Trait implemented on buffers so that they can be appended to a simple descriptor set builder. +pub unsafe trait SimpleDescriptorSetBufferExt { + /// The new type of the template parameter `R` of the builder. + type Out; + + /// Appends the buffer to the `SimpleDescriptorSetBuilder`. + // TODO: return Result + fn add_me(self, i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder; +} + +unsafe impl SimpleDescriptorSetBufferExt for T + where T: BufferAccess, + L: PipelineLayoutAbstract +{ + type Out = (R, SimpleDescriptorSetBuf); + + fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder { + let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead + assert_eq!(set_id, i.set_id); // TODO: Result instead + let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead + + assert!(desc.array_count == 1); // not implemented i.writes.push(match desc.ty.ty().unwrap() { - DescriptorType::UniformBuffer => unsafe { - DescriptorWrite::uniform_buffer(binding_id as u32, 0, &self) - }, - DescriptorType::StorageBuffer => unsafe { - DescriptorWrite::storage_buffer(binding_id as u32, 0, &self) - }, - _ => panic!() - }); - - SimpleDescriptorSetBuilder { - layout: i.layout, - set_id: i.set_id, - writes: i.writes, - resources: (i.resources, SimpleDescriptorSetBuf { - buffer: self, - write: !desc.readonly, - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: - }) - } - } -} - -/// Trait implemented on images so that they can be appended to a simple descriptor set builder. -pub unsafe trait SimpleDescriptorSetImageExt { - /// The new type of the template parameter `R` of the builder. - type Out; - - /// Appends the image to the `SimpleDescriptorSetBuilder`. - // TODO: return Result - fn add_me(self, i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder; -} - -unsafe impl SimpleDescriptorSetImageExt for T - where T: ImageViewAccess, L: PipelineLayoutAbstract -{ - type Out = (R, SimpleDescriptorSetImg); - - fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder - { - let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead - assert_eq!(set_id, i.set_id); // TODO: Result instead - let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead - - assert!(desc.array_count == 1); // not implemented + DescriptorType::UniformBuffer => unsafe { + DescriptorWrite::uniform_buffer(binding_id as u32, 0, &self) + }, + DescriptorType::StorageBuffer => unsafe { + DescriptorWrite::storage_buffer(binding_id as u32, 0, &self) + }, + _ => panic!(), + }); + + SimpleDescriptorSetBuilder { + layout: i.layout, + set_id: i.set_id, + writes: i.writes, + resources: (i.resources, + SimpleDescriptorSetBuf { + buffer: self, + write: !desc.readonly, + stage: PipelineStages::none(), // FIXME: + access: AccessFlagBits::none(), // FIXME: + }), + } + } +} + +/// Trait implemented on images so that they can be appended to a simple descriptor set builder. +pub unsafe trait SimpleDescriptorSetImageExt { + /// The new type of the template parameter `R` of the builder. + type Out; + + /// Appends the image to the `SimpleDescriptorSetBuilder`. + // TODO: return Result + fn add_me(self, i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder; +} + +unsafe impl SimpleDescriptorSetImageExt for T + where T: ImageViewAccess, + L: PipelineLayoutAbstract +{ + type Out = (R, SimpleDescriptorSetImg); + + fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder { + let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead + assert_eq!(set_id, i.set_id); // TODO: Result instead + let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead + + assert!(desc.array_count == 1); // not implemented i.writes.push(match desc.ty.ty().unwrap() { - DescriptorType::SampledImage => { - DescriptorWrite::sampled_image(binding_id as u32, 0, &self) - }, - DescriptorType::StorageImage => { - DescriptorWrite::storage_image(binding_id as u32, 0, &self) - }, - DescriptorType::InputAttachment => { - DescriptorWrite::input_attachment(binding_id as u32, 0, &self) - }, - _ => panic!() - }); - - SimpleDescriptorSetBuilder { - layout: i.layout, - set_id: i.set_id, - writes: i.writes, - resources: (i.resources, SimpleDescriptorSetImg { - image: self, - sampler: None, - write: !desc.readonly, - first_mipmap: 0, // FIXME: - num_mipmaps: 1, // FIXME: - first_layer: 0, // FIXME: - num_layers: 1, // FIXME: - layout: ImageLayout::General, // FIXME: - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: - }) - } - } -} - -unsafe impl SimpleDescriptorSetImageExt for (T, Arc) - where T: ImageViewAccess, L: PipelineLayoutAbstract -{ - type Out = (R, SimpleDescriptorSetImg); - - fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder - { - let image_view = self.0; - - let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead - assert_eq!(set_id, i.set_id); // TODO: Result instead - let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead - - assert!(desc.array_count == 1); // not implemented + DescriptorType::SampledImage => { + DescriptorWrite::sampled_image(binding_id as u32, 0, &self) + }, + DescriptorType::StorageImage => { + DescriptorWrite::storage_image(binding_id as u32, 0, &self) + }, + DescriptorType::InputAttachment => { + DescriptorWrite::input_attachment(binding_id as u32, 0, &self) + }, + _ => panic!(), + }); + + SimpleDescriptorSetBuilder { + layout: i.layout, + set_id: i.set_id, + writes: i.writes, + resources: (i.resources, + SimpleDescriptorSetImg { + image: self, + sampler: None, + write: !desc.readonly, + first_mipmap: 0, // FIXME: + num_mipmaps: 1, // FIXME: + first_layer: 0, // FIXME: + num_layers: 1, // FIXME: + layout: ImageLayout::General, // FIXME: + stage: PipelineStages::none(), // FIXME: + access: AccessFlagBits::none(), // FIXME: + }), + } + } +} + +unsafe impl SimpleDescriptorSetImageExt for (T, Arc) + where T: ImageViewAccess, + L: PipelineLayoutAbstract +{ + type Out = (R, SimpleDescriptorSetImg); + + fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder { + let image_view = self.0; + + let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead + assert_eq!(set_id, i.set_id); // TODO: Result instead + let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead + + assert!(desc.array_count == 1); // not implemented i.writes.push(match desc.ty.ty().unwrap() { - DescriptorType::CombinedImageSampler => { - DescriptorWrite::combined_image_sampler(binding_id as u32, 0, &self.1, &image_view) - }, - _ => panic!() - }); - - SimpleDescriptorSetBuilder { - layout: i.layout, - set_id: i.set_id, - writes: i.writes, - resources: (i.resources, SimpleDescriptorSetImg { - image: image_view, - sampler: Some(self.1), - write: !desc.readonly, - first_mipmap: 0, // FIXME: - num_mipmaps: 1, // FIXME: - first_layer: 0, // FIXME: - num_layers: 1, // FIXME: - layout: ImageLayout::General, // FIXME: - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: - }) - } - } -} - -// TODO: DRY -unsafe impl SimpleDescriptorSetImageExt for Vec<(T, Arc)> - where T: ImageViewAccess, L: PipelineLayoutAbstract -{ - type Out = (R, Vec>); - - fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) - -> SimpleDescriptorSetBuilder - { - let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead - assert_eq!(set_id, i.set_id); // TODO: Result instead - let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead - - assert_eq!(desc.array_count as usize, self.len()); // not implemented - - let mut imgs = Vec::new(); - for (num, (img, sampler)) in self.into_iter().enumerate() { + DescriptorType::CombinedImageSampler => { + DescriptorWrite::combined_image_sampler(binding_id as u32, + 0, + &self.1, + &image_view) + }, + _ => panic!(), + }); + + SimpleDescriptorSetBuilder { + layout: i.layout, + set_id: i.set_id, + writes: i.writes, + resources: (i.resources, + SimpleDescriptorSetImg { + image: image_view, + sampler: Some(self.1), + write: !desc.readonly, + first_mipmap: 0, // FIXME: + num_mipmaps: 1, // FIXME: + first_layer: 0, // FIXME: + num_layers: 1, // FIXME: + layout: ImageLayout::General, // FIXME: + stage: PipelineStages::none(), // FIXME: + access: AccessFlagBits::none(), // FIXME: + }), + } + } +} + +// TODO: DRY +unsafe impl SimpleDescriptorSetImageExt for Vec<(T, Arc)> + where T: ImageViewAccess, + L: PipelineLayoutAbstract +{ + type Out = (R, Vec>); + + fn add_me(self, mut i: SimpleDescriptorSetBuilder, name: &str) + -> SimpleDescriptorSetBuilder { + let (set_id, binding_id) = i.layout.descriptor_by_name(name).unwrap(); // TODO: Result instead + assert_eq!(set_id, i.set_id); // TODO: Result instead + let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead + + assert_eq!(desc.array_count as usize, self.len()); // not implemented + + let mut imgs = Vec::new(); + for (num, (img, sampler)) in self.into_iter().enumerate() { i.writes.push(match desc.ty.ty().unwrap() { - DescriptorType::CombinedImageSampler => { - DescriptorWrite::combined_image_sampler(binding_id as u32, num as u32, - &sampler, &img) - }, - _ => panic!() - }); - - imgs.push(SimpleDescriptorSetImg { - image: img, - sampler: Some(sampler), - write: !desc.readonly, - first_mipmap: 0, // FIXME: - num_mipmaps: 1, // FIXME: - first_layer: 0, // FIXME: - num_layers: 1, // FIXME: - layout: ImageLayout::General, // FIXME: - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: - }); - } - - SimpleDescriptorSetBuilder { - layout: i.layout, - set_id: i.set_id, - writes: i.writes, - resources: (i.resources, imgs), - } - } -} - + DescriptorType::CombinedImageSampler => { + DescriptorWrite::combined_image_sampler(binding_id as u32, + num as u32, + &sampler, + &img) + }, + _ => panic!(), + }); + + imgs.push(SimpleDescriptorSetImg { + image: img, + sampler: Some(sampler), + write: !desc.readonly, + first_mipmap: 0, // FIXME: + num_mipmaps: 1, // FIXME: + first_layer: 0, // FIXME: + num_layers: 1, // FIXME: + layout: ImageLayout::General, // FIXME: + stage: PipelineStages::none(), // FIXME: + access: AccessFlagBits::none(), // FIXME: + }); + } + + SimpleDescriptorSetBuilder { + layout: i.layout, + set_id: i.set_id, + writes: i.writes, + resources: (i.resources, imgs), + } + } +} + /* /// Internal trait related to the `SimpleDescriptorSet` system. pub unsafe trait SimpleDescriptorSetResourcesCollection { @@ -394,16 +418,16 @@ unsafe impl SimpleDescriptorSetResourcesCollection for () { #[inline] fn add_transition<'a>(&'a self, _: &mut CommandsListSink<'a>) { } -}*/ - -/// Internal object related to the `SimpleDescriptorSet` system. -pub struct SimpleDescriptorSetBuf { - buffer: B, - write: bool, - stage: PipelineStages, - access: AccessFlagBits, -} - +}*/ + +/// Internal object related to the `SimpleDescriptorSet` system. +pub struct SimpleDescriptorSetBuf { + buffer: B, + write: bool, + stage: PipelineStages, + access: AccessFlagBits, +} + /*unsafe impl SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBuf where B: BufferAccess { @@ -425,16 +449,18 @@ pub struct SimpleDescriptorSetBuf { sink.add_buffer_transition(&self.buffer, 0, self.buffer.size(), self.write, stages, access); } -}*/ - -/// Internal object related to the `SimpleDescriptorSet` system. -pub struct SimpleDescriptorSetBufView where V: BufferViewRef { - view: V, - write: bool, - stage: PipelineStages, - access: AccessFlagBits, -} - +}*/ + +/// Internal object related to the `SimpleDescriptorSet` system. +pub struct SimpleDescriptorSetBufView + where V: BufferViewRef +{ + view: V, + write: bool, + stage: PipelineStages, + access: AccessFlagBits, +} + /*unsafe impl SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBufView where V: BufferViewRef, V::BufferAccess: BufferAccess { @@ -457,22 +483,22 @@ pub struct SimpleDescriptorSetBufView where V: BufferViewRef { sink.add_buffer_transition(self.view.view().buffer(), 0, self.view.view().buffer().size(), self.write, stages, access); } -}*/ - -/// Internal object related to the `SimpleDescriptorSet` system. -pub struct SimpleDescriptorSetImg { - image: I, - sampler: Option>, - write: bool, - first_mipmap: u32, - num_mipmaps: u32, - first_layer: u32, - num_layers: u32, - layout: ImageLayout, - stage: PipelineStages, - access: AccessFlagBits, -} - +}*/ + +/// Internal object related to the `SimpleDescriptorSet` system. +pub struct SimpleDescriptorSetImg { + image: I, + sampler: Option>, + write: bool, + first_mipmap: u32, + num_mipmaps: u32, + first_layer: u32, + num_layers: u32, + layout: ImageLayout, + stage: PipelineStages, + access: AccessFlagBits, +} + /*unsafe impl SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetImg where I: ImageViewAccess { @@ -509,4 +535,4 @@ unsafe impl SimpleDescriptorSetResourcesCollection for (A, B) self.0.add_transition(sink); self.1.add_transition(sink); } -}*/ +}*/ diff --git a/vulkano/src/descriptor/descriptor_set/std_pool.rs b/vulkano/src/descriptor/descriptor_set/std_pool.rs index 97d21342..1769dbe8 100644 --- a/vulkano/src/descriptor/descriptor_set/std_pool.rs +++ b/vulkano/src/descriptor/descriptor_set/std_pool.rs @@ -1,172 +1,172 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. -use std::sync::Arc; -use std::sync::Mutex; +use std::sync::Arc; +use std::sync::Mutex; -use device::Device; -use device::DeviceOwned; -use descriptor::descriptor_set::DescriptorsCount; -use descriptor::descriptor_set::DescriptorPool; -use descriptor::descriptor_set::DescriptorPoolAlloc; -use descriptor::descriptor_set::DescriptorPoolAllocError; -use descriptor::descriptor_set::UnsafeDescriptorPool; -use descriptor::descriptor_set::UnsafeDescriptorSet; -use descriptor::descriptor_set::UnsafeDescriptorSetLayout; -use OomError; - -/// Standard implementation of a descriptor pool. -/// -/// Whenever a set is allocated, this implementation will try to find a pool that has some space -/// for it. If there is one, allocate from it. If there is none, create a new pool whose capacity -/// is 40 sets and 40 times the requested descriptors. This number is arbitrary. -pub struct StdDescriptorPool { - device: Arc, - pools: Mutex>>>, -} - -struct Pool { - pool: UnsafeDescriptorPool, - remaining_capacity: DescriptorsCount, - remaining_sets_count: u32, -} - -impl StdDescriptorPool { - /// Builds a new `StdDescriptorPool`. - pub fn new(device: Arc) -> StdDescriptorPool { - StdDescriptorPool { - device: device, - pools: Mutex::new(Vec::new()), - } - } -} - -/// A descriptor set allocated from a `StdDescriptorPool`. -pub struct StdDescriptorPoolAlloc { - pool: Arc>, - // The set. Inside an option so that we can extract it in the destructor. - set: Option, - // We need to keep track of this count in order to add it back to the capacity when freeing. - descriptors: DescriptorsCount, -} - -unsafe impl DescriptorPool for Arc { - type Alloc = StdDescriptorPoolAlloc; - - // TODO: eventually use a lock-free algorithm? - fn alloc(&self, layout: &UnsafeDescriptorSetLayout) - -> Result - { - let mut pools = self.pools.lock().unwrap(); - - // Try find an existing pool with some free space. - for pool_arc in pools.iter_mut() { - let mut pool = pool_arc.lock().unwrap(); - - if pool.remaining_sets_count == 0 { - continue; - } - - if !(pool.remaining_capacity >= *layout.descriptors_count()) { - continue; - } - - // Note that we decrease these values *before* trying to allocate from the pool. - // If allocating from the pool results in an error, we just ignore it. In order to - // avoid trying the same failing pool every time, we "pollute" it by reducing the - // available space. - pool.remaining_sets_count -= 1; - pool.remaining_capacity -= *layout.descriptors_count(); - - let alloc = unsafe { +use OomError; +use descriptor::descriptor_set::DescriptorPool; +use descriptor::descriptor_set::DescriptorPoolAlloc; +use descriptor::descriptor_set::DescriptorPoolAllocError; +use descriptor::descriptor_set::DescriptorsCount; +use descriptor::descriptor_set::UnsafeDescriptorPool; +use descriptor::descriptor_set::UnsafeDescriptorSet; +use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use device::Device; +use device::DeviceOwned; + +/// Standard implementation of a descriptor pool. +/// +/// Whenever a set is allocated, this implementation will try to find a pool that has some space +/// for it. If there is one, allocate from it. If there is none, create a new pool whose capacity +/// is 40 sets and 40 times the requested descriptors. This number is arbitrary. +pub struct StdDescriptorPool { + device: Arc, + pools: Mutex>>>, +} + +struct Pool { + pool: UnsafeDescriptorPool, + remaining_capacity: DescriptorsCount, + remaining_sets_count: u32, +} + +impl StdDescriptorPool { + /// Builds a new `StdDescriptorPool`. + pub fn new(device: Arc) -> StdDescriptorPool { + StdDescriptorPool { + device: device, + pools: Mutex::new(Vec::new()), + } + } +} + +/// A descriptor set allocated from a `StdDescriptorPool`. +pub struct StdDescriptorPoolAlloc { + pool: Arc>, + // The set. Inside an option so that we can extract it in the destructor. + set: Option, + // We need to keep track of this count in order to add it back to the capacity when freeing. + descriptors: DescriptorsCount, +} + +unsafe impl DescriptorPool for Arc { + type Alloc = StdDescriptorPoolAlloc; + + // TODO: eventually use a lock-free algorithm? + fn alloc(&self, layout: &UnsafeDescriptorSetLayout) + -> Result { + let mut pools = self.pools.lock().unwrap(); + + // Try find an existing pool with some free space. + for pool_arc in pools.iter_mut() { + let mut pool = pool_arc.lock().unwrap(); + + if pool.remaining_sets_count == 0 { + continue; + } + + if !(pool.remaining_capacity >= *layout.descriptors_count()) { + continue; + } + + // Note that we decrease these values *before* trying to allocate from the pool. + // If allocating from the pool results in an error, we just ignore it. In order to + // avoid trying the same failing pool every time, we "pollute" it by reducing the + // available space. + pool.remaining_sets_count -= 1; + pool.remaining_capacity -= *layout.descriptors_count(); + + let alloc = unsafe { match pool.pool.alloc(Some(layout)) { Ok(mut sets) => sets.next().unwrap(), - // An error can happen if we're out of memory, or if the pool is fragmented. - // We handle these errors by just ignoring this pool and trying the next ones. + // An error can happen if we're out of memory, or if the pool is fragmented. + // We handle these errors by just ignoring this pool and trying the next ones. Err(_) => continue, - } - }; - - return Ok(StdDescriptorPoolAlloc { - pool: pool_arc.clone(), - set: Some(alloc), - descriptors: *layout.descriptors_count(), - }); - } - - // No existing pool can be used. Create a new one. - // We use an arbitrary number of 40 sets and 40 times the requested descriptors. - let count = layout.descriptors_count().clone() * 40; - // Failure to allocate a new pool results in an error for the whole function because - // there's no way we can recover from that. - let mut new_pool = try!(UnsafeDescriptorPool::new(self.device.clone(), &count, 40, true)); - - let alloc = unsafe { + } + }; + + return Ok(StdDescriptorPoolAlloc { + pool: pool_arc.clone(), + set: Some(alloc), + descriptors: *layout.descriptors_count(), + }); + } + + // No existing pool can be used. Create a new one. + // We use an arbitrary number of 40 sets and 40 times the requested descriptors. + let count = layout.descriptors_count().clone() * 40; + // Failure to allocate a new pool results in an error for the whole function because + // there's no way we can recover from that. + let mut new_pool = UnsafeDescriptorPool::new(self.device.clone(), &count, 40, true)?; + + let alloc = unsafe { match new_pool.alloc(Some(layout)) { Ok(mut sets) => sets.next().unwrap(), - Err(DescriptorPoolAllocError::OutOfHostMemory) => { - return Err(OomError::OutOfHostMemory); + Err(DescriptorPoolAllocError::OutOfHostMemory) => { + return Err(OomError::OutOfHostMemory); }, - Err(DescriptorPoolAllocError::OutOfDeviceMemory) => { - return Err(OomError::OutOfDeviceMemory); + Err(DescriptorPoolAllocError::OutOfDeviceMemory) => { + return Err(OomError::OutOfDeviceMemory); }, - // A fragmented pool error can't happen at the first ever allocation. + // A fragmented pool error can't happen at the first ever allocation. Err(DescriptorPoolAllocError::FragmentedPool) => unreachable!(), - // Out of pool memory cannot happen at the first ever allocation. + // Out of pool memory cannot happen at the first ever allocation. Err(DescriptorPoolAllocError::OutOfPoolMemory) => unreachable!(), - } - }; - - let pool_obj = Arc::new(Mutex::new(Pool { - pool: new_pool, - remaining_capacity: count - *layout.descriptors_count(), - remaining_sets_count: 40 - 1, - })); - - pools.push(pool_obj.clone()); - - Ok(StdDescriptorPoolAlloc { - pool: pool_obj, - set: Some(alloc), - descriptors: *layout.descriptors_count(), - }) - } -} - -unsafe impl DeviceOwned for StdDescriptorPool { - #[inline] - fn device(&self) -> &Arc { - &self.device - } -} - -impl DescriptorPoolAlloc for StdDescriptorPoolAlloc { - #[inline] - fn inner(&self) -> &UnsafeDescriptorSet { - self.set.as_ref().unwrap() - } - - #[inline] - fn inner_mut(&mut self) -> &mut UnsafeDescriptorSet { - self.set.as_mut().unwrap() - } -} - -impl Drop for StdDescriptorPoolAlloc { - // This is the destructor of a single allocation (not of the whole pool). - fn drop(&mut self) { - unsafe { - let mut pool = self.pool.lock().unwrap(); - pool.pool.free(self.set.take()).unwrap(); - // Add back the capacity only after freeing, in case of a panic during the free. - pool.remaining_sets_count += 1; - pool.remaining_capacity += self.descriptors; - } - } -} + } + }; + + let pool_obj = Arc::new(Mutex::new(Pool { + pool: new_pool, + remaining_capacity: count - + *layout.descriptors_count(), + remaining_sets_count: 40 - 1, + })); + + pools.push(pool_obj.clone()); + + Ok(StdDescriptorPoolAlloc { + pool: pool_obj, + set: Some(alloc), + descriptors: *layout.descriptors_count(), + }) + } +} + +unsafe impl DeviceOwned for StdDescriptorPool { + #[inline] + fn device(&self) -> &Arc { + &self.device + } +} + +impl DescriptorPoolAlloc for StdDescriptorPoolAlloc { + #[inline] + fn inner(&self) -> &UnsafeDescriptorSet { + self.set.as_ref().unwrap() + } + + #[inline] + fn inner_mut(&mut self) -> &mut UnsafeDescriptorSet { + self.set.as_mut().unwrap() + } +} + +impl Drop for StdDescriptorPoolAlloc { + // This is the destructor of a single allocation (not of the whole pool). + fn drop(&mut self) { + unsafe { + let mut pool = self.pool.lock().unwrap(); + pool.pool.free(self.set.take()).unwrap(); + // Add back the capacity only after freeing, in case of a panic during the free. + pool.remaining_sets_count += 1; + pool.remaining_capacity += self.descriptors; + } + } +} diff --git a/vulkano/src/descriptor/descriptor_set/sys.rs b/vulkano/src/descriptor/descriptor_set/sys.rs index d0980e71..d84ed26b 100644 --- a/vulkano/src/descriptor/descriptor_set/sys.rs +++ b/vulkano/src/descriptor/descriptor_set/sys.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::cmp; use std::error; use std::fmt; @@ -15,7 +16,6 @@ use std::ops; use std::ptr; use std::sync::Arc; use std::vec::IntoIter as VecIntoIter; -use smallvec::SmallVec; use buffer::BufferAccess; use buffer::BufferInner; @@ -27,9 +27,9 @@ use device::DeviceOwned; use image::ImageViewAccess; use sampler::Sampler; -use check_errors; use OomError; use VulkanObject; +use check_errors; use vk; /// A pool from which descriptor sets can be allocated. @@ -238,8 +238,8 @@ impl UnsafeDescriptorPool { /// - Panics if `max_sets` is 0. /// pub fn new(device: Arc, count: &DescriptorsCount, max_sets: u32, - free_descriptor_set_bit: bool) -> Result - { + free_descriptor_set_bit: bool) + -> Result { let vk = device.pointers(); assert_ne!(max_sets, 0, "The maximum number of sets can't be 0"); @@ -259,17 +259,23 @@ impl UnsafeDescriptorPool { elem!(uniform_buffer, vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER); elem!(storage_buffer, vk::DESCRIPTOR_TYPE_STORAGE_BUFFER); - elem!(uniform_buffer_dynamic, vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); - elem!(storage_buffer_dynamic, vk::DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); - elem!(uniform_texel_buffer, vk::DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); - elem!(storage_texel_buffer, vk::DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); + elem!(uniform_buffer_dynamic, + vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); + elem!(storage_buffer_dynamic, + vk::DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); + elem!(uniform_texel_buffer, + vk::DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + elem!(storage_texel_buffer, + vk::DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); elem!(sampled_image, vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE); elem!(storage_image, vk::DESCRIPTOR_TYPE_STORAGE_IMAGE); elem!(sampler, vk::DESCRIPTOR_TYPE_SAMPLER); - elem!(combined_image_sampler, vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + elem!(combined_image_sampler, + vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); elem!(input_attachment, vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT); - assert!(!pool_sizes.is_empty(), "All the descriptors count of a pool are 0"); + assert!(!pool_sizes.is_empty(), + "All the descriptors count of a pool are 0"); let pool = unsafe { let infos = vk::DescriptorPoolCreateInfo { @@ -286,15 +292,17 @@ impl UnsafeDescriptorPool { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateDescriptorPool(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateDescriptorPool(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(UnsafeDescriptorPool { - pool: pool, - device: device.clone(), - }) + pool: pool, + device: device.clone(), + }) } /// Allocates descriptor sets from the pool, one for each layout. @@ -321,19 +329,23 @@ impl UnsafeDescriptorPool { -> Result where I: IntoIterator { - let layouts: SmallVec<[_; 8]> = layouts.into_iter().map(|l| { - assert_eq!(self.device.internal_object(), l.device().internal_object(), - "Tried to allocate from a pool with a set layout of a different device"); - l.internal_object() - }).collect(); + let layouts: SmallVec<[_; 8]> = layouts + .into_iter() + .map(|l| { + assert_eq!(self.device.internal_object(), + l.device().internal_object(), + "Tried to allocate from a pool with a set layout of a different \ + device"); + l.internal_object() + }) + .collect(); self.alloc_impl(&layouts) } // Actual implementation of `alloc`. Separated so that it is not inlined. unsafe fn alloc_impl(&mut self, layouts: &SmallVec<[vk::DescriptorSetLayout; 8]>) - -> Result - { + -> Result { let num = layouts.len(); if num == 0 { @@ -351,8 +363,8 @@ impl UnsafeDescriptorPool { let mut output = Vec::with_capacity(num); let vk = self.device.pointers(); - let ret = vk.AllocateDescriptorSets(self.device.internal_object(), &infos, - output.as_mut_ptr()); + let ret = + vk.AllocateDescriptorSets(self.device.internal_object(), &infos, output.as_mut_ptr()); // According to the specs, because `VK_ERROR_FRAGMENTED_POOL` was added after version // 1.0 of Vulkan, any negative return value except out-of-memory errors must be @@ -370,14 +382,12 @@ impl UnsafeDescriptorPool { c if (c as i32) < 0 => { return Err(DescriptorPoolAllocError::FragmentedPool); }, - _ => () + _ => (), }; output.set_len(num); - Ok(UnsafeDescriptorPoolAllocIter { - sets: output.into_iter(), - }) + Ok(UnsafeDescriptorPoolAllocIter { sets: output.into_iter() }) } /// Frees some descriptor sets. @@ -406,11 +416,12 @@ impl UnsafeDescriptorPool { // Actual implementation of `free`. Separated so that it is not inlined. unsafe fn free_impl(&mut self, sets: &SmallVec<[vk::DescriptorSet; 8]>) - -> Result<(), OomError> - { + -> Result<(), OomError> { let vk = self.device.pointers(); - try!(check_errors(vk.FreeDescriptorSets(self.device.internal_object(), self.pool, - sets.len() as u32, sets.as_ptr()))); + check_errors(vk.FreeDescriptorSets(self.device.internal_object(), + self.pool, + sets.len() as u32, + sets.as_ptr()))?; Ok(()) } @@ -419,8 +430,9 @@ impl UnsafeDescriptorPool { /// This destroys all descriptor sets and empties the pool. pub unsafe fn reset(&mut self) -> Result<(), OomError> { let vk = self.device.pointers(); - try!(check_errors(vk.ResetDescriptorPool(self.device.internal_object(), self.pool, - 0 /* reserved flags */))); + check_errors(vk.ResetDescriptorPool(self.device.internal_object(), + self.pool, + 0 /* reserved flags */))?; Ok(()) } } @@ -479,7 +491,7 @@ impl error::Error for DescriptorPoolAllocError { }, DescriptorPoolAllocError::OutOfPoolMemory => { "there is no more space available in the descriptor pool" - } + }, } } } @@ -502,9 +514,7 @@ impl Iterator for UnsafeDescriptorPoolAllocIter { #[inline] fn next(&mut self) -> Option { - self.sets.next().map(|s| UnsafeDescriptorSet { - set: s, - }) + self.sets.next().map(|s| UnsafeDescriptorSet { set: s }) } #[inline] @@ -581,17 +591,17 @@ impl UnsafeDescriptorSet { // The whole struct that wr write here is valid, except for pImageInfo, pBufferInfo // and pTexelBufferView which are placeholder values. raw_writes.push(vk::WriteDescriptorSet { - sType: vk::STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - pNext: ptr::null(), - dstSet: self.set, - dstBinding: indiv_write.binding, - dstArrayElement: indiv_write.first_array_element, - descriptorCount: indiv_write.inner.len() as u32, - descriptorType: indiv_write.ty() as u32, - pImageInfo: ptr::null(), - pBufferInfo: ptr::null(), - pTexelBufferView: ptr::null(), - }); + sType: vk::STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + pNext: ptr::null(), + dstSet: self.set, + dstBinding: indiv_write.binding, + dstArrayElement: indiv_write.first_array_element, + descriptorCount: indiv_write.inner.len() as u32, + descriptorType: indiv_write.ty() as u32, + pImageInfo: ptr::null(), + pBufferInfo: ptr::null(), + pTexelBufferView: ptr::null(), + }); match indiv_write.inner[0] { DescriptorWriteInner::Sampler(_) | @@ -624,53 +634,53 @@ impl UnsafeDescriptorSet { DescriptorWriteInner::UniformBuffer(buffer, offset, size) | DescriptorWriteInner::DynamicUniformBuffer(buffer, offset, size) => { buffer_descriptors.push(vk::DescriptorBufferInfo { - buffer: buffer, - offset: offset as u64, - range: size as u64, - }); + buffer: buffer, + offset: offset as u64, + range: size as u64, + }); }, DescriptorWriteInner::StorageBuffer(buffer, offset, size) | DescriptorWriteInner::DynamicStorageBuffer(buffer, offset, size) => { buffer_descriptors.push(vk::DescriptorBufferInfo { - buffer: buffer, - offset: offset as u64, - range: size as u64, - }); + buffer: buffer, + offset: offset as u64, + range: size as u64, + }); }, DescriptorWriteInner::Sampler(sampler) => { image_descriptors.push(vk::DescriptorImageInfo { - sampler: sampler, - imageView: 0, - imageLayout: 0, - }); + sampler: sampler, + imageView: 0, + imageLayout: 0, + }); }, DescriptorWriteInner::CombinedImageSampler(sampler, view, layout) => { image_descriptors.push(vk::DescriptorImageInfo { - sampler: sampler, - imageView: view, - imageLayout: layout, - }); + sampler: sampler, + imageView: view, + imageLayout: layout, + }); }, DescriptorWriteInner::StorageImage(view, layout) => { image_descriptors.push(vk::DescriptorImageInfo { - sampler: 0, - imageView: view, - imageLayout: layout, - }); + sampler: 0, + imageView: view, + imageLayout: layout, + }); }, DescriptorWriteInner::SampledImage(view, layout) => { image_descriptors.push(vk::DescriptorImageInfo { - sampler: 0, - imageView: view, - imageLayout: layout, - }); + sampler: 0, + imageView: view, + imageLayout: layout, + }); }, DescriptorWriteInner::InputAttachment(view, layout) => { image_descriptors.push(vk::DescriptorImageInfo { - sampler: 0, - imageView: view, - imageLayout: layout, - }); + sampler: 0, + imageView: view, + imageLayout: layout, + }); }, DescriptorWriteInner::UniformTexelBuffer(view) | DescriptorWriteInner::StorageTexelBuffer(view) => { @@ -685,25 +695,28 @@ impl UnsafeDescriptorSet { for (i, write) in raw_writes.iter_mut().enumerate() { write.pImageInfo = match raw_writes_img_infos[i] { Some(off) => image_descriptors.as_ptr().offset(off as isize), - None => ptr::null() + None => ptr::null(), }; write.pBufferInfo = match raw_writes_buf_infos[i] { Some(off) => buffer_descriptors.as_ptr().offset(off as isize), - None => ptr::null() + None => ptr::null(), }; write.pTexelBufferView = match raw_writes_buf_view_infos[i] { Some(off) => buffer_views_descriptors.as_ptr().offset(off as isize), - None => ptr::null() + None => ptr::null(), }; } // It is forbidden to call `vkUpdateDescriptorSets` with 0 writes, so we need to perform // this emptiness check. if !raw_writes.is_empty() { - vk.UpdateDescriptorSets(device.internal_object(), raw_writes.len() as u32, - raw_writes.as_ptr(), 0, ptr::null()); + vk.UpdateDescriptorSets(device.internal_object(), + raw_writes.len() as u32, + raw_writes.as_ptr(), + 0, + ptr::null()); } } } @@ -761,9 +774,10 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - let layout = image.descriptor_set_storage_image_layout() as u32; - DescriptorWriteInner::StorageImage(image.inner().internal_object(), layout) - }), + let layout = image.descriptor_set_storage_image_layout() as u32; + DescriptorWriteInner::StorageImage(image.inner().internal_object(), + layout) + }), } } @@ -772,7 +786,7 @@ impl DescriptorWrite { DescriptorWrite { binding: binding, first_array_element: array_element, - inner: smallvec!(DescriptorWriteInner::Sampler(sampler.internal_object())) + inner: smallvec!(DescriptorWriteInner::Sampler(sampler.internal_object())), } } @@ -784,30 +798,41 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - let layout = image.descriptor_set_sampled_image_layout() as u32; - DescriptorWriteInner::SampledImage(image.inner().internal_object(), layout) - }), + let layout = image.descriptor_set_sampled_image_layout() as u32; + DescriptorWriteInner::SampledImage(image.inner().internal_object(), + layout) + }), } } #[inline] - pub fn combined_image_sampler(binding: u32, array_element: u32, sampler: &Arc, image: &I) -> DescriptorWrite + pub fn combined_image_sampler(binding: u32, array_element: u32, sampler: &Arc, + image: &I) + -> DescriptorWrite where I: ImageViewAccess { DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - let layout = image.descriptor_set_combined_image_sampler_layout() as u32; - DescriptorWriteInner::CombinedImageSampler(sampler.internal_object(), image.inner().internal_object(), layout) - }), + let layout = + image.descriptor_set_combined_image_sampler_layout() as u32; + DescriptorWriteInner::CombinedImageSampler(sampler + .internal_object(), + image + .inner() + .internal_object(), + layout) + }), } } #[inline] - pub fn uniform_texel_buffer<'a, F, B>(binding: u32, array_element: u32, view: &Arc>) -> DescriptorWrite + pub fn uniform_texel_buffer<'a, F, B>(binding: u32, array_element: u32, + view: &Arc>) + -> DescriptorWrite where B: BufferAccess, - F: 'static + Send + Sync, + F: 'static + Send + Sync { assert!(view.uniform_texel_buffer()); @@ -819,9 +844,11 @@ impl DescriptorWrite { } #[inline] - pub fn storage_texel_buffer<'a, F, B>(binding: u32, array_element: u32, view: &Arc>) -> DescriptorWrite + pub fn storage_texel_buffer<'a, F, B>(binding: u32, array_element: u32, + view: &Arc>) + -> DescriptorWrite where B: BufferAccess + 'static, - F: 'static + Send + Sync, + F: 'static + Send + Sync { assert!(view.storage_texel_buffer()); @@ -843,8 +870,10 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - DescriptorWriteInner::UniformBuffer(buffer.internal_object(), offset, size) - }), + DescriptorWriteInner::UniformBuffer(buffer.internal_object(), + offset, + size) + }), } } @@ -859,13 +888,16 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - DescriptorWriteInner::StorageBuffer(buffer.internal_object(), offset, size) - }), + DescriptorWriteInner::StorageBuffer(buffer.internal_object(), + offset, + size) + }), } } #[inline] - pub unsafe fn dynamic_uniform_buffer(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite + pub unsafe fn dynamic_uniform_buffer(binding: u32, array_element: u32, buffer: &B) + -> DescriptorWrite where B: BufferAccess { let size = buffer.size(); @@ -875,12 +907,14 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!(DescriptorWriteInner::DynamicUniformBuffer(buffer.internal_object(), - offset, size)), + offset, + size)), } } #[inline] - pub unsafe fn dynamic_storage_buffer(binding: u32, array_element: u32, buffer: &B) -> DescriptorWrite + pub unsafe fn dynamic_storage_buffer(binding: u32, array_element: u32, buffer: &B) + -> DescriptorWrite where B: BufferAccess { let size = buffer.size(); @@ -890,7 +924,8 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!(DescriptorWriteInner::DynamicStorageBuffer(buffer.internal_object(), - offset, size)), + offset, + size)), } } @@ -902,9 +937,12 @@ impl DescriptorWrite { binding: binding, first_array_element: array_element, inner: smallvec!({ - let layout = image.descriptor_set_input_attachment_layout() as u32; - DescriptorWriteInner::InputAttachment(image.inner().internal_object(), layout) - }), + let layout = image.descriptor_set_input_attachment_layout() as u32; + DescriptorWriteInner::InputAttachment(image + .inner() + .internal_object(), + layout) + }), } } @@ -913,15 +951,18 @@ impl DescriptorWrite { pub fn ty(&self) -> DescriptorType { match self.inner[0] { DescriptorWriteInner::Sampler(_) => DescriptorType::Sampler, - DescriptorWriteInner::CombinedImageSampler(_, _, _) => DescriptorType::CombinedImageSampler, + DescriptorWriteInner::CombinedImageSampler(_, _, _) => + DescriptorType::CombinedImageSampler, DescriptorWriteInner::SampledImage(_, _) => DescriptorType::SampledImage, DescriptorWriteInner::StorageImage(_, _) => DescriptorType::StorageImage, DescriptorWriteInner::UniformTexelBuffer(_) => DescriptorType::UniformTexelBuffer, DescriptorWriteInner::StorageTexelBuffer(_) => DescriptorType::StorageTexelBuffer, DescriptorWriteInner::UniformBuffer(_, _, _) => DescriptorType::UniformBuffer, DescriptorWriteInner::StorageBuffer(_, _, _) => DescriptorType::StorageBuffer, - DescriptorWriteInner::DynamicUniformBuffer(_, _, _) => DescriptorType::UniformBufferDynamic, - DescriptorWriteInner::DynamicStorageBuffer(_, _, _) => DescriptorType::StorageBufferDynamic, + DescriptorWriteInner::DynamicUniformBuffer(_, _, _) => + DescriptorType::UniformBufferDynamic, + DescriptorWriteInner::DynamicStorageBuffer(_, _, _) => + DescriptorType::StorageBufferDynamic, DescriptorWriteInner::InputAttachment(_, _) => DescriptorType::InputAttachment, } } @@ -929,22 +970,22 @@ impl DescriptorWrite { #[cfg(test)] mod tests { - use std::iter; + use descriptor::descriptor::DescriptorBufferContentDesc; + use descriptor::descriptor::DescriptorBufferDesc; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::DescriptorDescTy; - use descriptor::descriptor::DescriptorBufferDesc; - use descriptor::descriptor::DescriptorBufferContentDesc; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::DescriptorsCount; use descriptor::descriptor_set::UnsafeDescriptorPool; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; + use std::iter; #[test] fn pool_create() { let (device, _) = gfx_dev_and_queue!(); let desc = DescriptorsCount { uniform_buffer: 1, - .. DescriptorsCount::zero() + ..DescriptorsCount::zero() }; let _ = UnsafeDescriptorPool::new(device, &desc, 10, false).unwrap(); @@ -956,7 +997,7 @@ mod tests { let (device, _) = gfx_dev_and_queue!(); let desc = DescriptorsCount { uniform_buffer: 1, - .. DescriptorsCount::zero() + ..DescriptorsCount::zero() }; let _ = UnsafeDescriptorPool::new(device, &desc, 0, false); @@ -975,20 +1016,21 @@ mod tests { let layout = DescriptorDesc { ty: DescriptorDescTy::Buffer(DescriptorBufferDesc { - dynamic: Some(false), - storage: false, - content: DescriptorBufferContentDesc::F32, - }), + dynamic: Some(false), + storage: false, + content: DescriptorBufferContentDesc::F32, + }), array_count: 1, stages: ShaderStages::all_graphics(), readonly: true, }; - let set_layout = UnsafeDescriptorSetLayout::new(device.clone(), iter::once(Some(layout))).unwrap(); + let set_layout = UnsafeDescriptorSetLayout::new(device.clone(), iter::once(Some(layout))) + .unwrap(); let desc = DescriptorsCount { uniform_buffer: 10, - .. DescriptorsCount::zero() + ..DescriptorsCount::zero() }; let mut pool = UnsafeDescriptorPool::new(device, &desc, 10, false).unwrap(); @@ -1006,10 +1048,10 @@ mod tests { let layout = DescriptorDesc { ty: DescriptorDescTy::Buffer(DescriptorBufferDesc { - dynamic: Some(false), - storage: false, - content: DescriptorBufferContentDesc::F32, - }), + dynamic: Some(false), + storage: false, + content: DescriptorBufferContentDesc::F32, + }), array_count: 1, stages: ShaderStages::all_graphics(), readonly: true, @@ -1019,7 +1061,7 @@ mod tests { let desc = DescriptorsCount { uniform_buffer: 10, - .. DescriptorsCount::zero() + ..DescriptorsCount::zero() }; let mut pool = UnsafeDescriptorPool::new(device2, &desc, 10, false).unwrap(); @@ -1034,7 +1076,7 @@ mod tests { let desc = DescriptorsCount { uniform_buffer: 1, - .. DescriptorsCount::zero() + ..DescriptorsCount::zero() }; let mut pool = UnsafeDescriptorPool::new(device, &desc, 1, false).unwrap(); diff --git a/vulkano/src/descriptor/descriptor_set/unsafe_layout.rs b/vulkano/src/descriptor/descriptor_set/unsafe_layout.rs index d7b33dbf..1c68f689 100644 --- a/vulkano/src/descriptor/descriptor_set/unsafe_layout.rs +++ b/vulkano/src/descriptor/descriptor_set/unsafe_layout.rs @@ -7,15 +7,15 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::fmt; use std::mem; use std::ptr; use std::sync::Arc; -use smallvec::SmallVec; -use check_errors; use OomError; use VulkanObject; +use check_errors; use vk; use descriptor::descriptor::DescriptorDesc; @@ -49,26 +49,30 @@ impl UnsafeDescriptorSetLayout { { let mut descriptors_count = DescriptorsCount::zero(); - let bindings = descriptors.into_iter().enumerate().filter_map(|(binding, desc)| { - let desc = match desc { - Some(d) => d, - None => return None - }; + let bindings = descriptors + .into_iter() + .enumerate() + .filter_map(|(binding, desc)| { + let desc = match desc { + Some(d) => d, + None => return None, + }; - // FIXME: it is not legal to pass eg. the TESSELLATION_SHADER bit when the device - // doesn't have tess shaders enabled + // FIXME: it is not legal to pass eg. the TESSELLATION_SHADER bit when the device + // doesn't have tess shaders enabled - let ty = desc.ty.ty().unwrap(); // TODO: shouldn't panic - descriptors_count.add_one(ty); + let ty = desc.ty.ty().unwrap(); // TODO: shouldn't panic + descriptors_count.add_one(ty); - Some(vk::DescriptorSetLayoutBinding { - binding: binding as u32, - descriptorType: ty as u32, - descriptorCount: desc.array_count, - stageFlags: desc.stages.into(), - pImmutableSamplers: ptr::null(), // FIXME: not yet implemented + Some(vk::DescriptorSetLayoutBinding { + binding: binding as u32, + descriptorType: ty as u32, + descriptorCount: desc.array_count, + stageFlags: desc.stages.into(), + pImmutableSamplers: ptr::null(), // FIXME: not yet implemented + }) }) - }).collect::>(); + .collect::>(); // Note that it seems legal to have no descriptor at all in the set. @@ -76,23 +80,25 @@ impl UnsafeDescriptorSetLayout { let infos = vk::DescriptorSetLayoutCreateInfo { sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved bindingCount: bindings.len() as u32, pBindings: bindings.as_ptr(), }; let mut output = mem::uninitialized(); let vk = device.pointers(); - try!(check_errors(vk.CreateDescriptorSetLayout(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateDescriptorSetLayout(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(UnsafeDescriptorSetLayout { - layout: layout, - device: device, - descriptors_count: descriptors_count, - }) + layout: layout, + device: device, + descriptors_count: descriptors_count, + }) } /// Returns the number of descriptors of each type. @@ -132,22 +138,21 @@ impl Drop for UnsafeDescriptorSetLayout { fn drop(&mut self) { unsafe { let vk = self.device.pointers(); - vk.DestroyDescriptorSetLayout(self.device.internal_object(), self.layout, - ptr::null()); + vk.DestroyDescriptorSetLayout(self.device.internal_object(), self.layout, ptr::null()); } } } #[cfg(test)] mod tests { - use std::iter; + use descriptor::descriptor::DescriptorBufferContentDesc; + use descriptor::descriptor::DescriptorBufferDesc; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::DescriptorDescTy; - use descriptor::descriptor::DescriptorBufferDesc; - use descriptor::descriptor::DescriptorBufferContentDesc; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::DescriptorsCount; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; + use std::iter; #[test] fn empty() { @@ -161,10 +166,10 @@ mod tests { let layout = DescriptorDesc { ty: DescriptorDescTy::Buffer(DescriptorBufferDesc { - dynamic: Some(false), - storage: false, - content: DescriptorBufferContentDesc::F32, - }), + dynamic: Some(false), + storage: false, + content: DescriptorBufferContentDesc::F32, + }), array_count: 1, stages: ShaderStages::all_graphics(), readonly: true, @@ -172,9 +177,10 @@ mod tests { let sl = UnsafeDescriptorSetLayout::new(device.clone(), iter::once(Some(layout))).unwrap(); - assert_eq!(sl.descriptors_count(), &DescriptorsCount { - uniform_buffer: 1, - .. DescriptorsCount::zero() - }); + assert_eq!(sl.descriptors_count(), + &DescriptorsCount { + uniform_buffer: 1, + ..DescriptorsCount::zero() + }); } } diff --git a/vulkano/src/descriptor/pipeline_layout/empty.rs b/vulkano/src/descriptor/pipeline_layout/empty.rs index 3db40a8b..4eeaab49 100644 --- a/vulkano/src/descriptor/pipeline_layout/empty.rs +++ b/vulkano/src/descriptor/pipeline_layout/empty.rs @@ -15,15 +15,15 @@ use descriptor::pipeline_layout::PipelineLayoutDescPcRange; /// Description of an empty pipeline layout. /// /// # Example -/// +/// /// ``` /// # use std::sync::Arc; /// # use vulkano::device::Device; /// use vulkano::descriptor::pipeline_layout::EmptyPipelineDesc; /// use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc; -/// +/// /// # let device: Arc = return; -/// let pipeline_layout = EmptyPipelineDesc.build(device.clone()).unwrap(); +/// let pipeline_layout = EmptyPipelineDesc.build(device.clone()).unwrap(); /// ``` #[derive(Debug, Copy, Clone)] pub struct EmptyPipelineDesc; diff --git a/vulkano/src/descriptor/pipeline_layout/mod.rs b/vulkano/src/descriptor/pipeline_layout/mod.rs index c3e41405..d133b1fe 100644 --- a/vulkano/src/descriptor/pipeline_layout/mod.rs +++ b/vulkano/src/descriptor/pipeline_layout/mod.rs @@ -42,7 +42,7 @@ //! graphics pipeline as parameter. //! //! # Custom pipeline layouts -//! +//! //! In some situations, it is better (as in, faster) to share the same descriptor set or sets //! between multiple pipelines that each use different descriptors. To do so, you have to create a //! pipeline layout object in advance and pass it when you create the pipelines. @@ -57,10 +57,10 @@ pub use self::traits::PipelineLayoutAbstract; pub use self::traits::PipelineLayoutDesc; pub use self::traits::PipelineLayoutDescNames; pub use self::traits::PipelineLayoutDescPcRange; -pub use self::traits::PipelineLayoutSuperset; pub use self::traits::PipelineLayoutNotSupersetError; -pub use self::traits::PipelineLayoutSetsCompatible; pub use self::traits::PipelineLayoutPushConstantsCompatible; +pub use self::traits::PipelineLayoutSetsCompatible; +pub use self::traits::PipelineLayoutSuperset; pub use self::union::PipelineLayoutDescUnion; mod empty; diff --git a/vulkano/src/descriptor/pipeline_layout/sys.rs b/vulkano/src/descriptor/pipeline_layout/sys.rs index 79196647..a585915e 100644 --- a/vulkano/src/descriptor/pipeline_layout/sys.rs +++ b/vulkano/src/descriptor/pipeline_layout/sys.rs @@ -7,31 +7,31 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::mem; use std::ptr; use std::sync::Arc; -use smallvec::SmallVec; -use check_errors; use Error; use OomError; use VulkanObject; +use check_errors; use vk; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use descriptor::pipeline_layout::PipelineLayoutAbstract; use descriptor::pipeline_layout::PipelineLayoutDesc; use descriptor::pipeline_layout::PipelineLayoutDescNames; use descriptor::pipeline_layout::PipelineLayoutDescPcRange; -use descriptor::pipeline_layout::PipelineLayoutAbstract; use device::Device; use device::DeviceOwned; /// Wrapper around the `PipelineLayout` Vulkan object. Describes to the Vulkan implementation the -/// descriptor sets and push constants available to your shaders +/// descriptor sets and push constants available to your shaders pub struct PipelineLayout { device: Arc, layout: vk::PipelineLayout, @@ -39,7 +39,9 @@ pub struct PipelineLayout { desc: L, } -impl PipelineLayout where L: PipelineLayoutDesc { +impl PipelineLayout + where L: PipelineLayoutDesc +{ /// Creates a new `PipelineLayout`. /// /// # Panic @@ -48,8 +50,7 @@ impl PipelineLayout where L: PipelineLayoutDesc { /// device than the one passed as parameter. #[inline] pub fn new(device: Arc, desc: L) - -> Result, PipelineLayoutCreationError> - { + -> Result, PipelineLayoutCreationError> { let vk = device.pointers(); let limits = device.physical_device().limits(); @@ -58,24 +59,28 @@ impl PipelineLayout where L: PipelineLayoutDesc { let mut layouts: SmallVec<[_; 16]> = SmallVec::new(); for num in 0 .. desc.num_sets() { layouts.push(match desc.provided_set_layout(num) { - Some(l) => { - assert_eq!(l.device().internal_object(), device.internal_object()); - l - }, - None => { - let sets_iter = 0 .. desc.num_bindings_in_set(num).unwrap_or(0); - let desc_iter = sets_iter.map(|d| desc.descriptor(num, d)); - Arc::new(try!(UnsafeDescriptorSetLayout::new(device.clone(), desc_iter))) - }, - }); + Some(l) => { + assert_eq!(l.device().internal_object(), + device.internal_object()); + l + }, + None => { + let sets_iter = 0 .. + desc.num_bindings_in_set(num).unwrap_or(0); + let desc_iter = sets_iter.map(|d| desc.descriptor(num, d)); + Arc::new(UnsafeDescriptorSetLayout::new(device.clone(), + desc_iter)?) + }, + }); } layouts }; // Grab the list of `vkDescriptorSetLayout` objects from `layouts`. - let layouts_ids = layouts.iter().map(|l| { - l.internal_object() - }).collect::>(); + let layouts_ids = layouts + .iter() + .map(|l| l.internal_object()) + .collect::>(); // FIXME: must also check per-descriptor-type limits (eg. max uniform buffer descriptors) @@ -88,7 +93,11 @@ impl PipelineLayout where L: PipelineLayoutDesc { let mut out: SmallVec<[_; 8]> = SmallVec::new(); for pc_id in 0 .. desc.num_push_constants_ranges() { - let PipelineLayoutDescPcRange { offset, size, stages } = { + let PipelineLayoutDescPcRange { + offset, + size, + stages, + } = { match desc.push_constants_range(pc_id) { Some(o) => o, None => continue, @@ -104,10 +113,10 @@ impl PipelineLayout where L: PipelineLayoutDesc { } out.push(vk::PushConstantRange { - stageFlags: stages.into(), - offset: offset as u32, - size: size as u32, - }); + stageFlags: stages.into(), + offset: offset as u32, + size: size as u32, + }); } out @@ -117,17 +126,17 @@ impl PipelineLayout where L: PipelineLayoutDesc { // We check that with a debug_assert because it's supposed to be enforced by the // `PipelineLayoutDesc`. debug_assert!({ - let mut stages = 0; - let mut outcome = true; - for pc in push_constants.iter() { - if (stages & pc.stageFlags) != 0 { - outcome = false; - break; - } - stages &= pc.stageFlags; - } - outcome - }); + let mut stages = 0; + let mut outcome = true; + for pc in push_constants.iter() { + if (stages & pc.stageFlags) != 0 { + outcome = false; + break; + } + stages &= pc.stageFlags; + } + outcome + }); // FIXME: it is not legal to pass eg. the TESSELLATION_SHADER bit when the device doesn't // have tess shaders enabled @@ -137,7 +146,7 @@ impl PipelineLayout where L: PipelineLayoutDesc { let infos = vk::PipelineLayoutCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved setLayoutCount: layouts_ids.len() as u32, pSetLayouts: layouts_ids.as_ptr(), pushConstantRangeCount: push_constants.len() as u32, @@ -145,21 +154,25 @@ impl PipelineLayout where L: PipelineLayoutDesc { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreatePipelineLayout(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreatePipelineLayout(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(PipelineLayout { - device: device.clone(), - layout: layout, - layouts: layouts, - desc: desc, - }) + device: device.clone(), + layout: layout, + layouts: layouts, + desc: desc, + }) } } -impl PipelineLayout where L: PipelineLayoutDesc { +impl PipelineLayout + where L: PipelineLayoutDesc +{ /// Returns the description of the pipeline layout. #[inline] pub fn desc(&self) -> &L { @@ -167,7 +180,9 @@ impl PipelineLayout where L: PipelineLayoutDesc { } } -unsafe impl PipelineLayoutAbstract for PipelineLayout where D: PipelineLayoutDescNames { +unsafe impl PipelineLayoutAbstract for PipelineLayout + where D: PipelineLayoutDescNames +{ #[inline] fn sys(&self) -> PipelineLayoutSys { PipelineLayoutSys(&self.layout) @@ -179,7 +194,9 @@ unsafe impl PipelineLayoutAbstract for PipelineLayout where D: PipelineLay } } -unsafe impl PipelineLayoutDesc for PipelineLayout where D: PipelineLayoutDesc { +unsafe impl PipelineLayoutDesc for PipelineLayout + where D: PipelineLayoutDesc +{ #[inline] fn num_sets(&self) -> usize { self.desc.num_sets() @@ -206,7 +223,9 @@ unsafe impl PipelineLayoutDesc for PipelineLayout where D: PipelineLayoutD } } -unsafe impl PipelineLayoutDescNames for PipelineLayout where D: PipelineLayoutDescNames { +unsafe impl PipelineLayoutDescNames for PipelineLayout + where D: PipelineLayoutDescNames +{ #[inline] fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { self.desc.descriptor_by_name(name) @@ -220,7 +239,9 @@ unsafe impl DeviceOwned for PipelineLayout { } } -impl fmt::Debug for PipelineLayout where D: fmt::Debug { +impl fmt::Debug for PipelineLayout + where D: fmt::Debug +{ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt.debug_struct("PipelineLayout") .field("raw", &self.layout) @@ -293,7 +314,7 @@ impl error::Error for PipelineLayoutCreationError { fn cause(&self) -> Option<&error::Error> { match *self { PipelineLayoutCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -322,7 +343,7 @@ impl From for PipelineLayoutCreationError { err @ Error::OutOfDeviceMemory => { PipelineLayoutCreationError::OomError(OomError::from(err)) }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } diff --git a/vulkano/src/descriptor/pipeline_layout/traits.rs b/vulkano/src/descriptor/pipeline_layout/traits.rs index c12e8201..418bfbed 100644 --- a/vulkano/src/descriptor/pipeline_layout/traits.rs +++ b/vulkano/src/descriptor/pipeline_layout/traits.rs @@ -7,22 +7,22 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use std::cmp; use std::error; use std::fmt; -use std::cmp; use std::sync::Arc; +use SafeDeref; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::DescriptorSetsCollection; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; use descriptor::pipeline_layout::PipelineLayout; +use descriptor::pipeline_layout::PipelineLayoutCreationError; use descriptor::pipeline_layout::PipelineLayoutDescUnion; use descriptor::pipeline_layout::PipelineLayoutSys; -use descriptor::pipeline_layout::PipelineLayoutCreationError; use device::Device; use device::DeviceOwned; -use SafeDeref; /// Trait for objects that describe the layout of the descriptors and push constants of a pipeline. // TODO: meh for PipelineLayoutDescNames ; the `Names` thing shouldn't be mandatory @@ -40,7 +40,10 @@ pub unsafe trait PipelineLayoutAbstract: PipelineLayoutDescNames + DeviceOwned { fn descriptor_set_layout(&self, index: usize) -> Option<&Arc>; } -unsafe impl PipelineLayoutAbstract for T where T: SafeDeref, T::Target: PipelineLayoutAbstract { +unsafe impl PipelineLayoutAbstract for T + where T: SafeDeref, + T::Target: PipelineLayoutAbstract +{ #[inline] fn sys(&self) -> PipelineLayoutSys { (**self).sys() @@ -91,7 +94,9 @@ pub unsafe trait PipelineLayoutDesc { /// Builds the union of this layout and another. #[inline] - fn union(self, other: T) -> PipelineLayoutDescUnion where Self: Sized { + fn union(self, other: T) -> PipelineLayoutDescUnion + where Self: Sized + { PipelineLayoutDescUnion::new(self, other) } @@ -99,8 +104,7 @@ pub unsafe trait PipelineLayoutDesc { /// /// > **Note**: This is just a shortcut for `PipelineLayout::new`. #[inline] - fn build(self, device: Arc) - -> Result, PipelineLayoutCreationError> + fn build(self, device: Arc) -> Result, PipelineLayoutCreationError> where Self: Sized { PipelineLayout::new(device, self) @@ -120,7 +124,10 @@ pub struct PipelineLayoutDescPcRange { pub stages: ShaderStages, } -unsafe impl PipelineLayoutDesc for T where T: SafeDeref, T::Target: PipelineLayoutDesc { +unsafe impl PipelineLayoutDesc for T + where T: SafeDeref, + T::Target: PipelineLayoutDesc +{ #[inline] fn num_sets(&self) -> usize { (**self).num_sets() @@ -155,7 +162,10 @@ pub unsafe trait PipelineLayoutDescNames: PipelineLayoutDesc { fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)>; } -unsafe impl PipelineLayoutDescNames for T where T: SafeDeref, T::Target: PipelineLayoutDescNames { +unsafe impl PipelineLayoutDescNames for T + where T: SafeDeref, + T::Target: PipelineLayoutDescNames +{ #[inline] fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { (**self).descriptor_by_name(name) @@ -174,7 +184,8 @@ pub unsafe trait PipelineLayoutSuperset: PipelineLayoutDesc } unsafe impl PipelineLayoutSuperset for T - where T: PipelineLayoutDesc, U: PipelineLayoutDesc + where T: PipelineLayoutDesc, + U: PipelineLayoutDesc { fn ensure_superset_of(&self, other: &U) -> Result<(), PipelineLayoutNotSupersetError> { for set_num in 0 .. cmp::max(self.num_sets(), other.num_sets()) { @@ -183,10 +194,10 @@ unsafe impl PipelineLayoutSuperset for T if self_num_bindings < other_num_bindings { return Err(PipelineLayoutNotSupersetError::DescriptorsCountMismatch { - set_num: set_num as u32, - self_num_descriptors: self_num_bindings as u32, - other_num_descriptors: other_num_bindings as u32, - }); + set_num: set_num as u32, + self_num_descriptors: self_num_bindings as u32, + other_num_descriptors: other_num_bindings as u32, + }); } for desc_num in 0 .. other_num_bindings { @@ -200,11 +211,12 @@ unsafe impl PipelineLayoutSuperset for T }); } }, - (None, Some(_)) => return Err(PipelineLayoutNotSupersetError::ExpectedEmptyDescriptor { - set_num: set_num as u32, - descriptor: desc_num as u32, - }), - _ => () + (None, Some(_)) => + return Err(PipelineLayoutNotSupersetError::ExpectedEmptyDescriptor { + set_num: set_num as u32, + descriptor: desc_num as u32, + }), + _ => (), } } } @@ -222,14 +234,11 @@ pub enum PipelineLayoutNotSupersetError { DescriptorsCountMismatch { set_num: u32, self_num_descriptors: u32, - other_num_descriptors: u32 + other_num_descriptors: u32, }, /// Expected an empty descriptor, but got something instead. - ExpectedEmptyDescriptor { - set_num: u32, - descriptor: u32, - }, + ExpectedEmptyDescriptor { set_num: u32, descriptor: u32 }, /// Two descriptors are incompatible. IncompatibleDescriptors { @@ -263,7 +272,7 @@ impl fmt::Display for PipelineLayoutNotSupersetError { } } -/// Traits that allow determining whether +/// Traits that allow determining whether pub unsafe trait PipelineLayoutSetsCompatible: PipelineLayoutDesc where Other: DescriptorSetsCollection { @@ -272,7 +281,8 @@ pub unsafe trait PipelineLayoutSetsCompatible: PipelineLayoutDesc } unsafe impl PipelineLayoutSetsCompatible for T - where T: PipelineLayoutDesc, U: DescriptorSetsCollection + where T: PipelineLayoutDesc, + U: DescriptorSetsCollection { fn is_compatible(&self, sets: &U) -> bool { /*let mut other_descriptor_sets = DescriptorSetsCollection::description(sets); @@ -295,14 +305,15 @@ unsafe impl PipelineLayoutSetsCompatible for T } }*/ - // FIXME: + // FIXME: true } } -/// Traits that allow determining whether +/// Traits that allow determining whether // TODO: require a trait on Pc -pub unsafe trait PipelineLayoutPushConstantsCompatible: PipelineLayoutDesc { +pub unsafe trait PipelineLayoutPushConstantsCompatible + : PipelineLayoutDesc { /// Returns true if `Pc` can be used with a pipeline that uses `self` as layout. fn is_compatible(&self, &Pc) -> bool; } diff --git a/vulkano/src/descriptor/pipeline_layout/union.rs b/vulkano/src/descriptor/pipeline_layout/union.rs index 2ff920b8..ffbfe3b0 100644 --- a/vulkano/src/descriptor/pipeline_layout/union.rs +++ b/vulkano/src/descriptor/pipeline_layout/union.rs @@ -1,149 +1,157 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use std::cmp; -use std::sync::Arc; -use descriptor::descriptor::DescriptorDesc; -use descriptor::descriptor_set::UnsafeDescriptorSetLayout; -use descriptor::pipeline_layout::PipelineLayoutDesc; -use descriptor::pipeline_layout::PipelineLayoutDescNames; -use descriptor::pipeline_layout::PipelineLayoutDescPcRange; - -/// Contains the union of two pipeline layout description. -/// -/// If `A` and `B` both implement `PipelineLayoutDesc`, then this struct also implements -/// `PipelineLayoutDesc` and will correspond to the union of the `A` object and the `B` object. -pub struct PipelineLayoutDescUnion { - a: A, - b: B, -} - -impl PipelineLayoutDescUnion { - // FIXME: check collisions - pub fn new(a: A, b: B) -> PipelineLayoutDescUnion { - PipelineLayoutDescUnion { a: a, b: b } - } -} - -unsafe impl PipelineLayoutDesc for PipelineLayoutDescUnion - where A: PipelineLayoutDesc, B: PipelineLayoutDesc -{ - #[inline] - fn num_sets(&self) -> usize { - cmp::max(self.a.num_sets(), self.b.num_sets()) - } - - #[inline] - fn num_bindings_in_set(&self, set: usize) -> Option { - let a = self.a.num_bindings_in_set(set); - let b = self.b.num_bindings_in_set(set); +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. +use descriptor::descriptor::DescriptorDesc; +use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use descriptor::pipeline_layout::PipelineLayoutDesc; +use descriptor::pipeline_layout::PipelineLayoutDescNames; +use descriptor::pipeline_layout::PipelineLayoutDescPcRange; +use std::cmp; +use std::sync::Arc; + +/// Contains the union of two pipeline layout description. +/// +/// If `A` and `B` both implement `PipelineLayoutDesc`, then this struct also implements +/// `PipelineLayoutDesc` and will correspond to the union of the `A` object and the `B` object. +pub struct PipelineLayoutDescUnion { + a: A, + b: B, +} + +impl PipelineLayoutDescUnion { + // FIXME: check collisions + pub fn new(a: A, b: B) -> PipelineLayoutDescUnion { + PipelineLayoutDescUnion { a: a, b: b } + } +} + +unsafe impl PipelineLayoutDesc for PipelineLayoutDescUnion + where A: PipelineLayoutDesc, + B: PipelineLayoutDesc +{ + #[inline] + fn num_sets(&self) -> usize { + cmp::max(self.a.num_sets(), self.b.num_sets()) + } + + #[inline] + fn num_bindings_in_set(&self, set: usize) -> Option { + let a = self.a.num_bindings_in_set(set); + let b = self.b.num_bindings_in_set(set); + match (a, b) { (Some(a), Some(b)) => Some(cmp::max(a, b)), (Some(a), None) => Some(a), (None, Some(b)) => Some(b), (None, None) => None, - } - } - - #[inline] - fn descriptor(&self, set: usize, binding: usize) -> Option { - let a = self.a.descriptor(set, binding); - let b = self.b.descriptor(set, binding); - + } + } + + #[inline] + fn descriptor(&self, set: usize, binding: usize) -> Option { + let a = self.a.descriptor(set, binding); + let b = self.b.descriptor(set, binding); + match (a, b) { (Some(a), Some(b)) => Some(a.union(&b).expect("Can't be union-ed")), (Some(a), None) => Some(a), (None, Some(b)) => Some(b), (None, None) => None, - } - } - - #[inline] - fn provided_set_layout(&self, set: usize) -> Option> { - self.a.provided_set_layout(set).or(self.b.provided_set_layout(set)) - } - - #[inline] - fn num_push_constants_ranges(&self) -> usize { - // We simply call `push_constants_range` repeatidely to determine when it is over. - // TODO: consider caching this - (self.a.num_push_constants_ranges() ..).filter(|&n| { - self.push_constants_range(n).is_none() - }).next().unwrap() - } - - // TODO: needs tests - #[inline] - fn push_constants_range(&self, num: usize) -> Option { - // The strategy here is that we return the same ranges as `self.a`, except that if there - // happens to be a range with a similar stage in `self.b` then we adjust the offset and - // size of the range coming from `self.a` to include the range of `self.b`. - // - // After all the ranges of `self.a` have been returned, we return the ones from `self.b` - // that don't intersect with any range of `self.a`. - - if let Some(mut pc) = self.a.push_constants_range(num) { - // We try to find the ranges in `self.b` that share the same stages as us. - for n in 0 .. self.b.num_push_constants_ranges() { - let other_pc = self.b.push_constants_range(n).unwrap(); - - if other_pc.stages.intersects(&pc.stages) { - if other_pc.offset < pc.offset { - pc.size += pc.offset - other_pc.offset; - pc.size = cmp::max(pc.size, other_pc.size); - pc.offset = other_pc.offset; - - } else if other_pc.offset > pc.offset { - pc.size = cmp::max(pc.size, other_pc.size + (other_pc.offset - pc.offset)); - } - } - } - - return Some(pc); - } - - let mut num = num - self.a.num_push_constants_ranges(); - 'outer_loop: for b_r in 0 .. self.b.num_push_constants_ranges() { - let pc = self.b.push_constants_range(b_r).unwrap(); - - for n in 0 .. self.a.num_push_constants_ranges() { - let other_pc = self.a.push_constants_range(n).unwrap(); - if other_pc.stages.intersects(&pc.stages) { - continue 'outer_loop; - } - } - - if num == 0 { - return Some(pc); - } else { - num -= 1; - } - } - - None - } -} - -unsafe impl PipelineLayoutDescNames for PipelineLayoutDescUnion - where A: PipelineLayoutDescNames, B: PipelineLayoutDescNames -{ - #[inline] - fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { - let a = self.a.descriptor_by_name(name); - let b = self.b.descriptor_by_name(name); - + } + } + + #[inline] + fn provided_set_layout(&self, set: usize) -> Option> { + self.a + .provided_set_layout(set) + .or(self.b.provided_set_layout(set)) + } + + #[inline] + fn num_push_constants_ranges(&self) -> usize { + // We simply call `push_constants_range` repeatidely to determine when it is over. + // TODO: consider caching this + (self.a.num_push_constants_ranges() ..) + .filter(|&n| self.push_constants_range(n).is_none()) + .next() + .unwrap() + } + + // TODO: needs tests + #[inline] + fn push_constants_range(&self, num: usize) -> Option { + // The strategy here is that we return the same ranges as `self.a`, except that if there + // happens to be a range with a similar stage in `self.b` then we adjust the offset and + // size of the range coming from `self.a` to include the range of `self.b`. + // + // After all the ranges of `self.a` have been returned, we return the ones from `self.b` + // that don't intersect with any range of `self.a`. + + if let Some(mut pc) = self.a.push_constants_range(num) { + // We try to find the ranges in `self.b` that share the same stages as us. + for n in 0 .. self.b.num_push_constants_ranges() { + let other_pc = self.b.push_constants_range(n).unwrap(); + + if other_pc.stages.intersects(&pc.stages) { + if other_pc.offset < pc.offset { + pc.size += pc.offset - other_pc.offset; + pc.size = cmp::max(pc.size, other_pc.size); + pc.offset = other_pc.offset; + + } else if other_pc.offset > pc.offset { + pc.size = cmp::max(pc.size, other_pc.size + (other_pc.offset - pc.offset)); + } + } + } + + return Some(pc); + } + + let mut num = num - self.a.num_push_constants_ranges(); + 'outer_loop: for b_r in 0 .. self.b.num_push_constants_ranges() { + let pc = self.b.push_constants_range(b_r).unwrap(); + + for n in 0 .. self.a.num_push_constants_ranges() { + let other_pc = self.a.push_constants_range(n).unwrap(); + if other_pc.stages.intersects(&pc.stages) { + continue 'outer_loop; + } + } + + if num == 0 { + return Some(pc); + } else { + num -= 1; + } + } + + None + } +} + +unsafe impl PipelineLayoutDescNames for PipelineLayoutDescUnion + where A: PipelineLayoutDescNames, + B: PipelineLayoutDescNames +{ + #[inline] + fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { + let a = self.a.descriptor_by_name(name); + let b = self.b.descriptor_by_name(name); + match (a, b) { (None, None) => None, (Some(r), None) => Some(r), (None, Some(r)) => Some(r), - (Some(a), Some(b)) => { assert_eq!(a, b); Some(a) } - } - } -} + (Some(a), Some(b)) => { + assert_eq!(a, b); + Some(a) + }, + } + } +} diff --git a/vulkano/src/device.rs b/vulkano/src/device.rs index 8a0e68e0..7baf0730 100644 --- a/vulkano/src/device.rs +++ b/vulkano/src/device.rs @@ -89,10 +89,12 @@ //! //! TODO: write +use fnv::FnvHasher; +use smallvec::SmallVec; use std::collections::HashMap; use std::collections::hash_map::Entry; -use std::fmt; use std::error; +use std::fmt; use std::hash::BuildHasherDefault; use std::mem; use std::ops::Deref; @@ -101,8 +103,6 @@ use std::sync::Arc; use std::sync::Mutex; use std::sync::MutexGuard; use std::sync::Weak; -use smallvec::SmallVec; -use fnv::FnvHasher; use command_buffer::pool::StandardCommandPool; use descriptor::descriptor_set::StdDescriptorPool; @@ -129,15 +129,18 @@ pub struct Device { vk: vk::DevicePointers, standard_pool: Mutex>, standard_descriptor_pool: Mutex>, - standard_command_pools: Mutex, BuildHasherDefault>>, + standard_command_pools: + Mutex, BuildHasherDefault>>, features: Features, extensions: DeviceExtensions, } // The `StandardCommandPool` type doesn't implement Send/Sync, so we have to manually reimplement // them for the device itself. -unsafe impl Send for Device {} -unsafe impl Sync for Device {} +unsafe impl Send for Device { +} +unsafe impl Sync for Device { +} impl Device { /// Builds a new Vulkan device for the given physical device. @@ -161,10 +164,10 @@ impl Device { // TODO: return Arc and handle synchronization in the Queue // TODO: should take the PhysicalDevice by value pub fn new<'a, I, Ext>(phys: &'a PhysicalDevice, requested_features: &Features, - extensions: Ext, queue_families: I) + extensions: Ext, queue_families: I) -> Result<(Arc, QueuesIter), DeviceCreationError> where I: IntoIterator, f32)>, - Ext: Into, + Ext: Into { let queue_families = queue_families.into_iter(); @@ -186,14 +189,16 @@ impl Device { // Because there's no way to query the list of layers enabled for an instance, we need // to save it alongside the instance. (`vkEnumerateDeviceLayerProperties` should get // the right list post-1.0.13, but not pre-1.0.13, so we can't use it here.) - let layers_ptr = phys.instance().loaded_layers().map(|layer| { - layer.as_ptr() - }).collect::>(); + let layers_ptr = phys.instance() + .loaded_layers() + .map(|layer| layer.as_ptr()) + .collect::>(); let extensions = extensions.into(); - let extensions_list = extensions.iter().map(|extension| { - extension.as_ptr() - }).collect::>(); + let extensions_list = extensions + .iter() + .map(|extension| extension.as_ptr()) + .collect::>(); // device creation let device = unsafe { @@ -223,16 +228,19 @@ impl Device { } // turning `queues` into an array of `vkDeviceQueueCreateInfo` suitable for Vulkan - let queues = queues.iter().map(|&(queue_id, ref priorities)| { - vk::DeviceQueueCreateInfo { - sType: vk::STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - queueFamilyIndex: queue_id, - queueCount: priorities.len() as u32, - pQueuePriorities: priorities.as_ptr() - } - }).collect::>(); + let queues = queues + .iter() + .map(|&(queue_id, ref priorities)| { + vk::DeviceQueueCreateInfo { + sType: vk::STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + queueFamilyIndex: queue_id, + queueCount: priorities.len() as u32, + pQueuePriorities: priorities.as_ptr(), + } + }) + .collect::>(); // TODO: The plan regarding `robustBufferAccess` is to check the shaders' code to see // if they can possibly perform out-of-bounds reads and writes. If the user tries @@ -256,7 +264,7 @@ impl Device { let infos = vk::DeviceCreateInfo { sType: vk::STRUCTURE_TYPE_DEVICE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved queueCreateInfoCount: queues.len() as u32, pQueueCreateInfos: queues.as_ptr(), enabledLayerCount: layers_ptr.len() as u32, @@ -267,27 +275,30 @@ impl Device { }; let mut output = mem::uninitialized(); - try!(check_errors(vk_i.CreateDevice(phys.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk_i.CreateDevice(phys.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; // loading the function pointers of the newly-created device - let vk = vk::DevicePointers::load(|name| { - unsafe { vk_i.GetDeviceProcAddr(device, name.as_ptr()) as *const _ } - }); + let vk = vk::DevicePointers::load(|name| unsafe { + vk_i.GetDeviceProcAddr(device, name.as_ptr()) as + *const _ + }); let device = Arc::new(Device { - instance: phys.instance().clone(), - physical_device: phys.index(), - device: device, - vk: vk, - standard_pool: Mutex::new(Weak::new()), - standard_descriptor_pool: Mutex::new(Weak::new()), - standard_command_pools: Mutex::new(Default::default()), - features: requested_features.clone(), - extensions: (&extensions).into(), - }); + instance: phys.instance().clone(), + physical_device: phys.index(), + device: device, + vk: vk, + standard_pool: Mutex::new(Weak::new()), + standard_descriptor_pool: Mutex::new(Weak::new()), + standard_command_pools: Mutex::new(Default::default()), + features: requested_features.clone(), + extensions: (&extensions).into(), + }); // Iterator for the produced queues. let output_queues = QueuesIter { @@ -317,7 +328,7 @@ impl Device { /// while this function is waiting. /// pub unsafe fn wait(&self) -> Result<(), OomError> { - try!(check_errors(self.vk.DeviceWaitIdle(self.device))); + check_errors(self.vk.DeviceWaitIdle(self.device))?; Ok(()) } @@ -397,7 +408,7 @@ impl Device { let new_pool = Arc::new(StandardCommandPool::new(me.clone(), queue)); entry.insert(Arc::downgrade(&new_pool)); new_pool - } + }, } } } @@ -439,7 +450,10 @@ pub unsafe trait DeviceOwned { fn device(&self) -> &Arc; } -unsafe impl DeviceOwned for T where T: Deref, T::Target: DeviceOwned { +unsafe impl DeviceOwned for T + where T: Deref, + T::Target: DeviceOwned +{ #[inline] fn device(&self) -> &Arc { (**self).device() @@ -460,20 +474,22 @@ impl Iterator for QueuesIter { unsafe { let &(family, id) = match self.families_and_ids.get(self.next_queue) { Some(a) => a, - None => return None + None => return None, }; self.next_queue += 1; let mut output = mem::uninitialized(); - self.device.vk.GetDeviceQueue(self.device.device, family, id, &mut output); + self.device + .vk + .GetDeviceQueue(self.device.device, family, id, &mut output); Some(Arc::new(Queue { - queue: Mutex::new(output), - device: self.device.clone(), - family: family, - id: id, - })) + queue: Mutex::new(output), + device: self.device.clone(), + family: family, + id: id, + })) } } @@ -484,7 +500,8 @@ impl Iterator for QueuesIter { } } -impl ExactSizeIterator for QueuesIter {} +impl ExactSizeIterator for QueuesIter { +} /// Error that can be returned when creating a device. #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -562,7 +579,7 @@ impl From for DeviceCreationError { Error::ExtensionNotPresent => DeviceCreationError::ExtensionNotPresent, Error::FeatureNotPresent => DeviceCreationError::FeatureNotPresent, Error::TooManyObjects => DeviceCreationError::TooManyObjects, - _ => panic!("Unexpected error value: {}", err as i32) + _ => panic!("Unexpected error value: {}", err as i32), } } } @@ -574,7 +591,7 @@ pub struct Queue { queue: Mutex, device: Arc, family: u32, - id: u32, // id within family + id: u32, // id within family } impl Queue { @@ -587,15 +604,17 @@ impl Queue { /// Returns true if this is the same queue as another one. #[inline] pub fn is_same(&self, other: &Queue) -> bool { - self.id == other.id && - self.family == other.family && + self.id == other.id && self.family == other.family && self.device.internal_object() == other.device.internal_object() } /// Returns the family this queue belongs to. #[inline] pub fn family(&self) -> QueueFamily { - self.device.physical_device().queue_family_by_id(self.family).unwrap() + self.device + .physical_device() + .queue_family_by_id(self.family) + .unwrap() } /// Returns the index of this queue within its family. @@ -612,7 +631,7 @@ impl Queue { unsafe { let vk = self.device.pointers(); let queue = self.queue.lock().unwrap(); - try!(check_errors(vk.QueueWaitIdle(*queue))); + check_errors(vk.QueueWaitIdle(*queue))?; Ok(()) } } @@ -629,12 +648,12 @@ unsafe impl SynchronizedVulkanObject for Queue { #[cfg(test)] mod tests { - use std::sync::Arc; use device::Device; use device::DeviceCreationError; use device::DeviceExtensions; use features::Features; use instance; + use std::sync::Arc; #[test] fn one_ref() { @@ -647,15 +666,18 @@ mod tests { let instance = instance!(); let physical = match instance::PhysicalDevice::enumerate(&instance).next() { Some(p) => p, - None => return + None => return, }; let family = physical.queue_families().next().unwrap(); let queues = (0 .. family.queues_count() + 1).map(|_| (family, 1.0)); - match Device::new(&physical, &Features::none(), &DeviceExtensions::none(), queues) { + match Device::new(&physical, + &Features::none(), + &DeviceExtensions::none(), + queues) { Err(DeviceCreationError::TooManyQueuesForFamily) => return, // Success - _ => panic!() + _ => panic!(), }; } @@ -664,7 +686,7 @@ mod tests { let instance = instance!(); let physical = match instance::PhysicalDevice::enumerate(&instance).next() { Some(p) => p, - None => return + None => return, }; let family = physical.queue_families().next().unwrap(); @@ -675,9 +697,12 @@ mod tests { return; } - match Device::new(&physical, &features, &DeviceExtensions::none(), Some((family, 1.0))) { + match Device::new(&physical, + &features, + &DeviceExtensions::none(), + Some((family, 1.0))) { Err(DeviceCreationError::FeatureNotPresent) => return, // Success - _ => panic!() + _ => panic!(), }; } @@ -686,23 +711,25 @@ mod tests { let instance = instance!(); let physical = match instance::PhysicalDevice::enumerate(&instance).next() { Some(p) => p, - None => return + None => return, }; let family = physical.queue_families().next().unwrap(); - match Device::new(&physical, &Features::none(), - &DeviceExtensions::none(), Some((family, 1.4))) - { + match Device::new(&physical, + &Features::none(), + &DeviceExtensions::none(), + Some((family, 1.4))) { Err(DeviceCreationError::PriorityOutOfRange) => (), // Success - _ => panic!() + _ => panic!(), }; - match Device::new(&physical, &Features::none(), - &DeviceExtensions::none(), Some((family, -0.2))) - { + match Device::new(&physical, + &Features::none(), + &DeviceExtensions::none(), + Some((family, -0.2))) { Err(DeviceCreationError::PriorityOutOfRange) => (), // Success - _ => panic!() + _ => panic!(), }; } } diff --git a/vulkano/src/format.rs b/vulkano/src/format.rs index b5324cdd..3d789e53 100644 --- a/vulkano/src/format.rs +++ b/vulkano/src/format.rs @@ -49,11 +49,11 @@ //! conversion. //! //! # Choosing a format -//! +//! //! The following formats are guaranteed to be supported for everything that is related to //! texturing (ie. blitting source and sampling them linearly). You should choose one of these //! formats if you have an image that you are going to sample from: -//! +//! //! // TODO: use vulkano enums //! - B4G4R4A4_UNORM_PACK16 //! - R5G6B5_UNORM_PACK16 @@ -101,6 +101,7 @@ //! //! // TODO: storage formats //! + use std::vec::IntoIter as VecIntoIter; use vk; @@ -120,11 +121,15 @@ pub unsafe trait Data { // TODO: that's just an example ; implement for all common data types unsafe impl Data for i8 { #[inline] - fn ty() -> Format { Format::R8Sint } + fn ty() -> Format { + Format::R8Sint + } } unsafe impl Data for u8 { #[inline] - fn ty() -> Format { Format::R8Uint } + fn ty() -> Format { + Format::R8Uint + } } macro_rules! formats { @@ -572,7 +577,7 @@ unsafe impl FormatDesc for Format { (FormatTy::Depth, f @ ClearValue::Depth(_)) => f, (FormatTy::Stencil, f @ ClearValue::Stencil(_)) => f, (FormatTy::DepthStencil, f @ ClearValue::DepthStencil(_)) => f, - _ => panic!("Wrong clear value") + _ => panic!("Wrong clear value"), } } } @@ -585,7 +590,9 @@ pub unsafe trait PossibleFloatFormatDesc: FormatDesc { unsafe impl PossibleFloatFormatDesc for Format { #[inline] - fn is_float(&self) -> bool { self.ty() == FormatTy::Float } + fn is_float(&self) -> bool { + self.ty() == FormatTy::Float + } } pub unsafe trait PossibleUintFormatDesc: FormatDesc { @@ -594,7 +601,9 @@ pub unsafe trait PossibleUintFormatDesc: FormatDesc { unsafe impl PossibleUintFormatDesc for Format { #[inline] - fn is_uint(&self) -> bool { self.ty() == FormatTy::Uint } + fn is_uint(&self) -> bool { + self.ty() == FormatTy::Uint + } } pub unsafe trait PossibleSintFormatDesc: FormatDesc { @@ -603,7 +612,9 @@ pub unsafe trait PossibleSintFormatDesc: FormatDesc { unsafe impl PossibleSintFormatDesc for Format { #[inline] - fn is_sint(&self) -> bool { self.ty() == FormatTy::Sint } + fn is_sint(&self) -> bool { + self.ty() == FormatTy::Sint + } } pub unsafe trait PossibleDepthFormatDesc: FormatDesc { @@ -612,7 +623,9 @@ pub unsafe trait PossibleDepthFormatDesc: FormatDesc { unsafe impl PossibleDepthFormatDesc for Format { #[inline] - fn is_depth(&self) -> bool { self.ty() == FormatTy::Depth } + fn is_depth(&self) -> bool { + self.ty() == FormatTy::Depth + } } pub unsafe trait PossibleStencilFormatDesc: FormatDesc { @@ -621,7 +634,9 @@ pub unsafe trait PossibleStencilFormatDesc: FormatDesc { unsafe impl PossibleStencilFormatDesc for Format { #[inline] - fn is_stencil(&self) -> bool { self.ty() == FormatTy::Stencil } + fn is_stencil(&self) -> bool { + self.ty() == FormatTy::Stencil + } } pub unsafe trait PossibleDepthStencilFormatDesc: FormatDesc { @@ -630,7 +645,9 @@ pub unsafe trait PossibleDepthStencilFormatDesc: FormatDesc { unsafe impl PossibleDepthStencilFormatDesc for Format { #[inline] - fn is_depth_stencil(&self) -> bool { self.ty() == FormatTy::DepthStencil } + fn is_depth_stencil(&self) -> bool { + self.ty() == FormatTy::DepthStencil + } } pub unsafe trait PossibleCompressedFormatDesc: FormatDesc { @@ -639,7 +656,9 @@ pub unsafe trait PossibleCompressedFormatDesc: FormatDesc { unsafe impl PossibleCompressedFormatDesc for Format { #[inline] - fn is_compressed(&self) -> bool { self.ty() == FormatTy::Compressed } + fn is_compressed(&self) -> bool { + self.ty() == FormatTy::Compressed + } } /// Trait for types that can possibly describe a float or compressed attachment. @@ -723,21 +742,21 @@ impl From<[f32; 4]> for ClearValue { impl From<[u32; 1]> for ClearValue { #[inline] fn from(val: [u32; 1]) -> ClearValue { - ClearValue::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct? + ClearValue::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct? } } impl From<[u32; 2]> for ClearValue { #[inline] fn from(val: [u32; 2]) -> ClearValue { - ClearValue::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct? + ClearValue::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct? } } impl From<[u32; 3]> for ClearValue { #[inline] fn from(val: [u32; 3]) -> ClearValue { - ClearValue::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct? + ClearValue::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct? } } @@ -751,21 +770,21 @@ impl From<[u32; 4]> for ClearValue { impl From<[i32; 1]> for ClearValue { #[inline] fn from(val: [i32; 1]) -> ClearValue { - ClearValue::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct? + ClearValue::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct? } } impl From<[i32; 2]> for ClearValue { #[inline] fn from(val: [i32; 2]) -> ClearValue { - ClearValue::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct? + ClearValue::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct? } } impl From<[i32; 3]> for ClearValue { #[inline] fn from(val: [i32; 3]) -> ClearValue { - ClearValue::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct? + ClearValue::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct? } } diff --git a/vulkano/src/framebuffer/attachments_list.rs b/vulkano/src/framebuffer/attachments_list.rs index 1e76aea7..4bb41508 100644 --- a/vulkano/src/framebuffer/attachments_list.rs +++ b/vulkano/src/framebuffer/attachments_list.rs @@ -1,53 +1,57 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. -use std::sync::Arc; -use SafeDeref; -use image::ImageViewAccess; -//use sync::AccessFlagBits; -//use sync::PipelineStages; - -/// A list of attachments. -// TODO: rework this trait -pub unsafe trait AttachmentsList { - // TODO: meh for API - fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess>; -} - -unsafe impl AttachmentsList for T where T: SafeDeref, T::Target: AttachmentsList { - #[inline] - fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { - (**self).as_image_view_accesses() - } -} - -unsafe impl AttachmentsList for () { - #[inline] - fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { - vec![] - } -} - -unsafe impl AttachmentsList for Vec> { - #[inline] - fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { - self.iter().map(|p| &**p as &ImageViewAccess).collect() - } -} - -unsafe impl AttachmentsList for (A, B) - where A: AttachmentsList, B: ImageViewAccess -{ - #[inline] - fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { - let mut list = self.0.as_image_view_accesses(); - list.push(&self.1); - list - } -} +use SafeDeref; +use image::ImageViewAccess; +use std::sync::Arc; +//use sync::AccessFlagBits; +//use sync::PipelineStages; + +/// A list of attachments. +// TODO: rework this trait +pub unsafe trait AttachmentsList { + // TODO: meh for API + fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess>; +} + +unsafe impl AttachmentsList for T + where T: SafeDeref, + T::Target: AttachmentsList +{ + #[inline] + fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { + (**self).as_image_view_accesses() + } +} + +unsafe impl AttachmentsList for () { + #[inline] + fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { + vec![] + } +} + +unsafe impl AttachmentsList for Vec> { + #[inline] + fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { + self.iter().map(|p| &**p as &ImageViewAccess).collect() + } +} + +unsafe impl AttachmentsList for (A, B) + where A: AttachmentsList, + B: ImageViewAccess +{ + #[inline] + fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> { + let mut list = self.0.as_image_view_accesses(); + list.push(&self.1); + list + } +} diff --git a/vulkano/src/framebuffer/compat_atch.rs b/vulkano/src/framebuffer/compat_atch.rs index 55447247..d41dfc12 100644 --- a/vulkano/src/framebuffer/compat_atch.rs +++ b/vulkano/src/framebuffer/compat_atch.rs @@ -10,11 +10,11 @@ //! This module contains the `ensure_image_view_compatible` function, which verifies whether //! an image view can be used as a render pass attachment. -use std::error; -use std::fmt; use format::Format; use framebuffer::RenderPassDesc; use image::ImageViewAccess; +use std::error; +use std::fmt; /// Checks whether the given image view is allowed to be the nth attachment of the given render /// pass. @@ -29,21 +29,22 @@ pub fn ensure_image_view_compatible(render_pass: &Rp, attachment_num: usi where Rp: ?Sized + RenderPassDesc, I: ?Sized + ImageViewAccess { - let attachment_desc = render_pass.attachment_desc(attachment_num) - .expect("Attachment num out of range"); + let attachment_desc = render_pass + .attachment_desc(attachment_num) + .expect("Attachment num out of range"); if image.format() != attachment_desc.format { return Err(IncompatibleRenderPassAttachmentError::FormatMismatch { - expected: attachment_desc.format, - obtained: image.format(), - }); + expected: attachment_desc.format, + obtained: image.format(), + }); } if image.samples() != attachment_desc.samples { return Err(IncompatibleRenderPassAttachmentError::SamplesMismatch { - expected: attachment_desc.samples, - obtained: image.samples(), - }); + expected: attachment_desc.samples, + obtained: image.samples(), + }); } if !image.identity_swizzle() { @@ -51,11 +52,16 @@ pub fn ensure_image_view_compatible(render_pass: &Rp, attachment_num: usi } for subpass_num in 0 .. render_pass.num_subpasses() { - let subpass = render_pass.subpass_desc(subpass_num).expect("Subpass num out of range ; \ - wrong RenderPassDesc trait impl"); + let subpass = render_pass + .subpass_desc(subpass_num) + .expect("Subpass num out of range ; wrong RenderPassDesc trait impl"); - if subpass.color_attachments.iter().any(|&(n, _)| n == attachment_num) { - debug_assert!(image.parent().has_color()); // Was normally checked by the render pass. + if subpass + .color_attachments + .iter() + .any(|&(n, _)| n == attachment_num) + { + debug_assert!(image.parent().has_color()); // Was normally checked by the render pass. if !image.parent().inner().usage_color_attachment() { return Err(IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage); } @@ -71,7 +77,11 @@ pub fn ensure_image_view_compatible(render_pass: &Rp, attachment_num: usi } } - if subpass.input_attachments.iter().any(|&(n, _)| n == attachment_num) { + if subpass + .input_attachments + .iter() + .any(|&(n, _)| n == attachment_num) + { if !image.parent().inner().usage_input_attachment() { return Err(IncompatibleRenderPassAttachmentError::MissingInputAttachmentUsage); } @@ -158,11 +168,11 @@ impl fmt::Display for IncompatibleRenderPassAttachmentError { #[cfg(test)] mod tests { + use super::IncompatibleRenderPassAttachmentError; + use super::ensure_image_view_compatible; use format::Format; use framebuffer::EmptySinglePassRenderPassDesc; use image::AttachmentImage; - use super::ensure_image_view_compatible; - use super::IncompatibleRenderPassAttachmentError; #[test] fn basic_ok() { @@ -184,7 +194,7 @@ mod tests { ).unwrap(); let img = AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(); - + ensure_image_view_compatible(&rp, 0, &img).unwrap(); } @@ -208,11 +218,13 @@ mod tests { ).unwrap(); let img = AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(); - + match ensure_image_view_compatible(&rp, 0, &img) { Err(IncompatibleRenderPassAttachmentError::FormatMismatch { - expected: Format::R16G16Sfloat, obtained: Format::R8G8B8A8Unorm }) => (), - e => panic!("{:?}", e) + expected: Format::R16G16Sfloat, + obtained: Format::R8G8B8A8Unorm, + }) => (), + e => panic!("{:?}", e), } } @@ -223,7 +235,7 @@ mod tests { let rp = EmptySinglePassRenderPassDesc; let img = AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(); - + let _ = ensure_image_view_compatible(&rp, 0, &img); } diff --git a/vulkano/src/framebuffer/desc.rs b/vulkano/src/framebuffer/desc.rs index 99f2131e..acb11350 100644 --- a/vulkano/src/framebuffer/desc.rs +++ b/vulkano/src/framebuffer/desc.rs @@ -14,10 +14,10 @@ use format::ClearValue; use format::Format; use format::FormatTy; use framebuffer::RenderPass; -use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassCompatible; use framebuffer::RenderPassCreationError; -use image::ImageLayout as ImageLayout; +use framebuffer::RenderPassDescClearValues; +use image::ImageLayout; use sync::AccessFlagBits; use sync::PipelineStages; @@ -53,8 +53,13 @@ pub unsafe trait RenderPassDesc: RenderPassDescClearValues> { /// Returns an iterator to the list of attachments. #[inline] - fn attachment_descs(&self) -> RenderPassDescAttachments where Self: Sized { - RenderPassDescAttachments { render_pass: self, num: 0 } + fn attachment_descs(&self) -> RenderPassDescAttachments + where Self: Sized + { + RenderPassDescAttachments { + render_pass: self, + num: 0, + } } /// Returns the number of subpasses of the render pass. @@ -67,8 +72,13 @@ pub unsafe trait RenderPassDesc: RenderPassDescClearValues> { /// Returns an iterator to the list of subpasses. #[inline] - fn subpass_descs(&self) -> RenderPassDescSubpasses where Self: Sized { - RenderPassDescSubpasses { render_pass: self, num: 0 } + fn subpass_descs(&self) -> RenderPassDescSubpasses + where Self: Sized + { + RenderPassDescSubpasses { + render_pass: self, + num: 0, + } } /// Returns the number of dependencies of the render pass. @@ -81,8 +91,13 @@ pub unsafe trait RenderPassDesc: RenderPassDescClearValues> { /// Returns an iterator to the list of dependencies. #[inline] - fn dependency_descs(&self) -> RenderPassDescDependencies where Self: Sized { - RenderPassDescDependencies { render_pass: self, num: 0 } + fn dependency_descs(&self) -> RenderPassDescDependencies + where Self: Sized + { + RenderPassDescDependencies { + render_pass: self, + num: 0, + } } /// Returns true if this render pass is compatible with another render pass. @@ -114,122 +129,191 @@ pub unsafe trait RenderPassDesc: RenderPassDescClearValues> { /// Returns the number of color attachments of a subpass. Returns `None` if out of range. #[inline] fn num_color_attachments(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| p.color_attachments.len() as u32) + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| p.color_attachments.len() as u32) } /// Returns the number of samples of the attachments of a subpass. Returns `None` if out of /// range or if the subpass has no attachment. TODO: return an enum instead? #[inline] fn num_samples(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().and_then(|p| { - // TODO: chain input attachments as well? - p.color_attachments.iter().cloned().chain(p.depth_stencil.clone().into_iter()) - .filter_map(|a| (&self).attachment_descs().skip(a.0).next()) - .next().map(|a| a.samples) - }) + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .and_then(|p| { + // TODO: chain input attachments as well? + p.color_attachments + .iter() + .cloned() + .chain(p.depth_stencil.clone().into_iter()) + .filter_map(|a| (&self).attachment_descs().skip(a.0).next()) + .next() + .map(|a| a.samples) + }) } /// Returns a tuple whose first element is `true` if there's a depth attachment, and whose /// second element is `true` if there's a stencil attachment. Returns `None` if out of range. #[inline] fn has_depth_stencil_attachment(&self, subpass: u32) -> Option<(bool, bool)> { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| { - let atch_num = match p.depth_stencil { - Some((d, _)) => d, - None => return (false, false) - }; + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| { + let atch_num = match p.depth_stencil { + Some((d, _)) => d, + None => return (false, false), + }; - match (&self).attachment_descs().skip(atch_num).next().unwrap().format.ty() { - FormatTy::Depth => (true, false), - FormatTy::Stencil => (false, true), - FormatTy::DepthStencil => (true, true), - _ => unreachable!() - } - }) + match (&self) + .attachment_descs() + .skip(atch_num) + .next() + .unwrap() + .format + .ty() { + FormatTy::Depth => (true, false), + FormatTy::Stencil => (false, true), + FormatTy::DepthStencil => (true, true), + _ => unreachable!(), + } + }) } /// Returns true if a subpass has a depth attachment or a depth-stencil attachment. #[inline] fn has_depth(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| { - let atch_num = match p.depth_stencil { - Some((d, _)) => d, - None => return false - }; + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| { + let atch_num = match p.depth_stencil { + Some((d, _)) => d, + None => return false, + }; - match (&self).attachment_descs().skip(atch_num).next().unwrap().format.ty() { - FormatTy::Depth => true, - FormatTy::Stencil => false, - FormatTy::DepthStencil => true, - _ => unreachable!() - } - }) + match (&self) + .attachment_descs() + .skip(atch_num) + .next() + .unwrap() + .format + .ty() { + FormatTy::Depth => true, + FormatTy::Stencil => false, + FormatTy::DepthStencil => true, + _ => unreachable!(), + } + }) } /// Returns true if a subpass has a depth attachment or a depth-stencil attachment whose /// layout is not `DepthStencilReadOnlyOptimal`. #[inline] fn has_writable_depth(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| { - let atch_num = match p.depth_stencil { - Some((d, l)) => { - if l == ImageLayout::DepthStencilReadOnlyOptimal { return false; } - d - }, - None => return false - }; + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| { + let atch_num = match p.depth_stencil { + Some((d, l)) => { + if l == ImageLayout::DepthStencilReadOnlyOptimal { + return false; + } + d + }, + None => return false, + }; - match (&self).attachment_descs().skip(atch_num).next().unwrap().format.ty() { - FormatTy::Depth => true, - FormatTy::Stencil => false, - FormatTy::DepthStencil => true, - _ => unreachable!() - } - }) + match (&self) + .attachment_descs() + .skip(atch_num) + .next() + .unwrap() + .format + .ty() { + FormatTy::Depth => true, + FormatTy::Stencil => false, + FormatTy::DepthStencil => true, + _ => unreachable!(), + } + }) } /// Returns true if a subpass has a stencil attachment or a depth-stencil attachment. #[inline] fn has_stencil(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| { - let atch_num = match p.depth_stencil { - Some((d, _)) => d, - None => return false - }; + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| { + let atch_num = match p.depth_stencil { + Some((d, _)) => d, + None => return false, + }; - match (&self).attachment_descs().skip(atch_num).next().unwrap().format.ty() { - FormatTy::Depth => false, - FormatTy::Stencil => true, - FormatTy::DepthStencil => true, - _ => unreachable!() - } - }) + match (&self) + .attachment_descs() + .skip(atch_num) + .next() + .unwrap() + .format + .ty() { + FormatTy::Depth => false, + FormatTy::Stencil => true, + FormatTy::DepthStencil => true, + _ => unreachable!(), + } + }) } /// Returns true if a subpass has a stencil attachment or a depth-stencil attachment whose /// layout is not `DepthStencilReadOnlyOptimal`. #[inline] fn has_writable_stencil(&self, subpass: u32) -> Option { - (&self).subpass_descs().skip(subpass as usize).next().map(|p| { - let atch_num = match p.depth_stencil { - Some((d, l)) => { - if l == ImageLayout::DepthStencilReadOnlyOptimal { return false; } - d - }, - None => return false - }; + (&self) + .subpass_descs() + .skip(subpass as usize) + .next() + .map(|p| { + let atch_num = match p.depth_stencil { + Some((d, l)) => { + if l == ImageLayout::DepthStencilReadOnlyOptimal { + return false; + } + d + }, + None => return false, + }; - match (&self).attachment_descs().skip(atch_num).next().unwrap().format.ty() { - FormatTy::Depth => false, - FormatTy::Stencil => true, - FormatTy::DepthStencil => true, - _ => unreachable!() - } - }) + match (&self) + .attachment_descs() + .skip(atch_num) + .next() + .unwrap() + .format + .ty() { + FormatTy::Depth => false, + FormatTy::Stencil => true, + FormatTy::DepthStencil => true, + _ => unreachable!(), + } + }) } } -unsafe impl RenderPassDesc for T where T: SafeDeref, T::Target: RenderPassDesc { +unsafe impl RenderPassDesc for T + where T: SafeDeref, + T::Target: RenderPassDesc +{ #[inline] fn num_attachments(&self) -> usize { (**self).num_attachments() @@ -268,14 +352,18 @@ pub struct RenderPassDescAttachments<'a, R: ?Sized + 'a> { num: usize, } -impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescAttachments<'a, R> where R: RenderPassDesc { +impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescAttachments<'a, R> + where R: RenderPassDesc +{ type Item = LayoutAttachmentDescription; fn next(&mut self) -> Option { if self.num < self.render_pass.num_attachments() { let n = self.num; self.num += 1; - Some(self.render_pass.attachment_desc(n).expect("Wrong RenderPassDesc implementation")) + Some(self.render_pass + .attachment_desc(n) + .expect("Wrong RenderPassDesc implementation")) } else { None } @@ -289,14 +377,18 @@ pub struct RenderPassDescSubpasses<'a, R: ?Sized + 'a> { num: usize, } -impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescSubpasses<'a, R> where R: RenderPassDesc { +impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescSubpasses<'a, R> + where R: RenderPassDesc +{ type Item = LayoutPassDescription; fn next(&mut self) -> Option { if self.num < self.render_pass.num_subpasses() { let n = self.num; self.num += 1; - Some(self.render_pass.subpass_desc(n).expect("Wrong RenderPassDesc implementation")) + Some(self.render_pass + .subpass_desc(n) + .expect("Wrong RenderPassDesc implementation")) } else { None } @@ -310,14 +402,18 @@ pub struct RenderPassDescDependencies<'a, R: ?Sized + 'a> { num: usize, } -impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescDependencies<'a, R> where R: RenderPassDesc { +impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescDependencies<'a, R> + where R: RenderPassDesc +{ type Item = LayoutPassDependencyDescription; fn next(&mut self) -> Option { if self.num < self.render_pass.num_dependencies() { let n = self.num; self.num += 1; - Some(self.render_pass.dependency_desc(n).expect("Wrong RenderPassDesc implementation")) + Some(self.render_pass + .dependency_desc(n) + .expect("Wrong RenderPassDesc implementation")) } else { None } @@ -389,22 +485,22 @@ impl LayoutAttachmentDescription { #[derive(Debug, Clone)] pub struct LayoutPassDescription { /// Indices and layouts of attachments to use as color attachments. - pub color_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow + pub color_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow /// Index and layout of the attachment to use as depth-stencil attachment. pub depth_stencil: Option<(usize, ImageLayout)>, /// Indices and layouts of attachments to use as input attachments. - pub input_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow + pub input_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow /// If not empty, each color attachment will be resolved into each corresponding entry of /// this list. /// /// If this value is not empty, it **must** be the same length as `color_attachments`. - pub resolve_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow + pub resolve_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow /// Indices of attachments that will be preserved during this pass. - pub preserve_attachments: Vec, // TODO: Vec is slow + pub preserve_attachments: Vec, // TODO: Vec is slow } /// Describes a dependency between two passes of a render pass. diff --git a/vulkano/src/framebuffer/empty.rs b/vulkano/src/framebuffer/empty.rs index c94cc5f0..36b7928b 100644 --- a/vulkano/src/framebuffer/empty.rs +++ b/vulkano/src/framebuffer/empty.rs @@ -7,13 +7,13 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::iter; use format::ClearValue; +use framebuffer::LayoutAttachmentDescription; +use framebuffer::LayoutPassDependencyDescription; +use framebuffer::LayoutPassDescription; use framebuffer::RenderPassDesc; use framebuffer::RenderPassDescClearValues; -use framebuffer::LayoutAttachmentDescription; -use framebuffer::LayoutPassDescription; -use framebuffer::LayoutPassDependencyDescription; +use std::iter; /// Description of an empty render pass. /// @@ -52,12 +52,12 @@ unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc { fn subpass_desc(&self, num: usize) -> Option { if num == 0 { Some(LayoutPassDescription { - color_attachments: vec![], - depth_stencil: None, - input_attachments: vec![], - resolve_attachments: vec![], - preserve_attachments: vec![], - }) + color_attachments: vec![], + depth_stencil: None, + input_attachments: vec![], + resolve_attachments: vec![], + preserve_attachments: vec![], + }) } else { None } @@ -75,11 +75,7 @@ unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc { #[inline] fn num_color_attachments(&self, subpass: u32) -> Option { - if subpass == 0 { - Some(0) - } else { - None - } + if subpass == 0 { Some(0) } else { None } } #[inline] @@ -98,45 +94,29 @@ unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc { #[inline] fn has_depth(&self, subpass: u32) -> Option { - if subpass == 0 { - Some(false) - } else { - None - } + if subpass == 0 { Some(false) } else { None } } #[inline] fn has_writable_depth(&self, subpass: u32) -> Option { - if subpass == 0 { - Some(false) - } else { - None - } + if subpass == 0 { Some(false) } else { None } } #[inline] fn has_stencil(&self, subpass: u32) -> Option { - if subpass == 0 { - Some(false) - } else { - None - } + if subpass == 0 { Some(false) } else { None } } #[inline] fn has_writable_stencil(&self, subpass: u32) -> Option { - if subpass == 0 { - Some(false) - } else { - None - } + if subpass == 0 { Some(false) } else { None } } } unsafe impl RenderPassDescClearValues> for EmptySinglePassRenderPassDesc { #[inline] fn convert_clear_values(&self, values: Vec) -> Box> { - assert!(values.is_empty()); // TODO: error instead + assert!(values.is_empty()); // TODO: error instead Box::new(iter::empty()) } } diff --git a/vulkano/src/framebuffer/framebuffer.rs b/vulkano/src/framebuffer/framebuffer.rs index ade85bd5..0cac7b10 100644 --- a/vulkano/src/framebuffer/framebuffer.rs +++ b/vulkano/src/framebuffer/framebuffer.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::cmp; use std::error; use std::fmt; @@ -14,7 +15,6 @@ use std::marker::PhantomData; use std::mem; use std::ptr; use std::sync::Arc; -use smallvec::SmallVec; use device::Device; use device::DeviceOwned; @@ -26,8 +26,8 @@ use framebuffer::LayoutAttachmentDescription; use framebuffer::LayoutPassDependencyDescription; use framebuffer::LayoutPassDescription; use framebuffer::RenderPassAbstract; -use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassDesc; +use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassSys; use framebuffer::ensure_image_view_compatible; use image::ImageViewAccess; @@ -129,7 +129,10 @@ pub struct FramebufferBuilder { attachments: A, } -impl fmt::Debug for FramebufferBuilder where Rp: fmt::Debug, A: fmt::Debug { +impl fmt::Debug for FramebufferBuilder + where Rp: fmt::Debug, + A: fmt::Debug +{ #[inline] fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt.debug_struct("FramebufferBuilder") @@ -149,7 +152,7 @@ enum FramebufferBuilderDimensions { impl FramebufferBuilder where Rp: RenderPassAbstract, - A: AttachmentsList, + A: AttachmentsList { /// Appends an attachment to the prototype of the framebuffer. /// @@ -160,14 +163,14 @@ impl FramebufferBuilder { if self.raw_ids.len() >= self.render_pass.num_attachments() { return Err(FramebufferCreationError::AttachmentsCountMismatch { - expected: self.render_pass.num_attachments(), - obtained: self.raw_ids.len() + 1, - }); + expected: self.render_pass.num_attachments(), + obtained: self.raw_ids.len() + 1, + }); } match ensure_image_view_compatible(&self.render_pass, self.raw_ids.len(), &attachment) { Ok(()) => (), - Err(err) => return Err(FramebufferCreationError::IncompatibleAttachment(err)) + Err(err) => return Err(FramebufferCreationError::IncompatibleAttachment(err)), }; let img_dims = attachment.dimensions(); @@ -180,16 +183,16 @@ impl FramebufferBuilder }, FramebufferBuilderDimensions::AutoIdentical(Some(current)) => { if img_dims.width() != current[0] || img_dims.height() != current[1] || - img_dims.array_layers() != current[2] + img_dims.array_layers() != current[2] { return Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected: current, - obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()] + obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()], }); } FramebufferBuilderDimensions::AutoIdentical(Some(current)) - } + }, FramebufferBuilderDimensions::AutoSmaller(None) => { let dims = [img_dims.width(), img_dims.height(), img_dims.array_layers()]; FramebufferBuilderDimensions::AutoSmaller(Some(dims)) @@ -198,38 +201,36 @@ impl FramebufferBuilder let new_dims = [ cmp::min(current[0], img_dims.width()), cmp::min(current[1], img_dims.height()), - cmp::min(current[2], img_dims.array_layers()) + cmp::min(current[2], img_dims.array_layers()), ]; FramebufferBuilderDimensions::AutoSmaller(Some(new_dims)) }, FramebufferBuilderDimensions::Specific(current) => { if img_dims.width() < current[0] || img_dims.height() < current[1] || - img_dims.array_layers() < current[2] + img_dims.array_layers() < current[2] { return Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected: current, - obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()] + obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()], }); } - FramebufferBuilderDimensions::Specific([ - img_dims.width(), - img_dims.height(), - img_dims.array_layers() - ]) - } + FramebufferBuilderDimensions::Specific( + [img_dims.width(), img_dims.height(), img_dims.array_layers()], + ) + }, }; - + let mut raw_ids = self.raw_ids; raw_ids.push(attachment.inner().internal_object()); Ok(FramebufferBuilder { - render_pass: self.render_pass, - raw_ids: raw_ids, - dimensions: dimensions, - attachments: (self.attachments, attachment), - }) + render_pass: self.render_pass, + raw_ids: raw_ids, + dimensions: dimensions, + attachments: (self.attachments, attachment), + }) } /// Turns this builder into a `FramebufferBuilder>`. @@ -258,9 +259,9 @@ impl FramebufferBuilder // Check the number of attachments. if self.raw_ids.len() != self.render_pass.num_attachments() { return Err(FramebufferCreationError::AttachmentsCountMismatch { - expected: self.render_pass.num_attachments(), - obtained: self.raw_ids.len(), - }); + expected: self.render_pass.num_attachments(), + obtained: self.raw_ids.len(), + }); } // Compute the dimensions. @@ -279,11 +280,12 @@ impl FramebufferBuilder // Checking the dimensions against the limits. { let limits = device.physical_device().limits(); - let limits = [limits.max_framebuffer_width(), limits.max_framebuffer_height(), - limits.max_framebuffer_layers()]; - if dimensions[0] > limits[0] || dimensions[1] > limits[1] || - dimensions[2] > limits[2] - { + let limits = [ + limits.max_framebuffer_width(), + limits.max_framebuffer_height(), + limits.max_framebuffer_layers(), + ]; + if dimensions[0] > limits[0] || dimensions[1] > limits[1] || dimensions[2] > limits[2] { return Err(FramebufferCreationError::DimensionsTooLarge); } } @@ -294,7 +296,7 @@ impl FramebufferBuilder let infos = vk::FramebufferCreateInfo { sType: vk::STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved renderPass: self.render_pass.inner().internal_object(), attachmentCount: self.raw_ids.len() as u32, pAttachments: self.raw_ids.as_ptr(), @@ -304,18 +306,20 @@ impl FramebufferBuilder }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateFramebuffer(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateFramebuffer(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Framebuffer { - device: device, - render_pass: self.render_pass, - framebuffer: framebuffer, - dimensions: dimensions, - resources: self.attachments, - }) + device: device, + render_pass: self.render_pass, + framebuffer: framebuffer, + dimensions: dimensions, + resources: self.attachments, + }) } } @@ -377,7 +381,9 @@ unsafe impl FramebufferAbstract for Framebuffer } } -unsafe impl RenderPassDesc for Framebuffer where Rp: RenderPassDesc { +unsafe impl RenderPassDesc for Framebuffer + where Rp: RenderPassDesc +{ #[inline] fn num_attachments(&self) -> usize { self.render_pass.num_attachments() @@ -392,7 +398,7 @@ unsafe impl RenderPassDesc for Framebuffer where Rp: RenderPassDes fn num_subpasses(&self) -> usize { self.render_pass.num_subpasses() } - + #[inline] fn subpass_desc(&self, num: usize) -> Option { self.render_pass.subpass_desc(num) @@ -418,7 +424,9 @@ unsafe impl RenderPassDescClearValues for Framebuffer } } -unsafe impl RenderPassAbstract for Framebuffer where Rp: RenderPassAbstract { +unsafe impl RenderPassAbstract for Framebuffer + where Rp: RenderPassAbstract +{ #[inline] fn inner(&self) -> RenderPassSys { self.render_pass.inner() @@ -494,8 +502,8 @@ impl error::Error for FramebufferCreationError { fn description(&self) -> &str { match *self { FramebufferCreationError::OomError(_) => "no memory available", - FramebufferCreationError::DimensionsTooLarge => "the dimensions of the framebuffer \ - are too large", + FramebufferCreationError::DimensionsTooLarge => + "the dimensions of the framebuffer are too large", FramebufferCreationError::AttachmentDimensionsIncompatible { .. } => { "the attachment has a size that isn't compatible with the framebuffer dimensions" }, @@ -537,19 +545,20 @@ impl From for FramebufferCreationError { #[cfg(test)] mod tests { - use std::sync::Arc; use format::Format; use framebuffer::EmptySinglePassRenderPassDesc; use framebuffer::Framebuffer; use framebuffer::FramebufferCreationError; use framebuffer::RenderPassDesc; use image::attachment::AttachmentImage; + use std::sync::Arc; #[test] fn simple_create() { let (device, _) = gfx_dev_and_queue!(); - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { color: { load: Clear, @@ -562,22 +571,29 @@ mod tests { color: [color], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); - let image = AttachmentImage::new(device.clone(), [1024, 768], - Format::R8G8B8A8Unorm).unwrap(); - let _ = Framebuffer::start(render_pass).add(image.clone()).unwrap().build().unwrap(); + let image = AttachmentImage::new(device.clone(), [1024, 768], Format::R8G8B8A8Unorm) + .unwrap(); + let _ = Framebuffer::start(render_pass) + .add(image.clone()) + .unwrap() + .build() + .unwrap(); } #[test] fn check_device_limits() { let (device, _) = gfx_dev_and_queue!(); - let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap(); + let rp = EmptySinglePassRenderPassDesc + .build_render_pass(device) + .unwrap(); let res = Framebuffer::with_dimensions(rp, [0xffffffff, 0xffffffff, 0xffffffff]).build(); match res { Err(FramebufferCreationError::DimensionsTooLarge) => (), - _ => panic!() + _ => panic!(), } } @@ -585,7 +601,8 @@ mod tests { fn attachment_format_mismatch() { let (device, _) = gfx_dev_and_queue!(); - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { color: { load: Clear, @@ -598,14 +615,14 @@ mod tests { color: [color], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); - let image = AttachmentImage::new(device.clone(), [1024, 768], - Format::R8Unorm).unwrap(); + let image = AttachmentImage::new(device.clone(), [1024, 768], Format::R8Unorm).unwrap(); match Framebuffer::start(render_pass).add(image.clone()) { Err(FramebufferCreationError::IncompatibleAttachment(_)) => (), - _ => panic!() + _ => panic!(), } } @@ -614,8 +631,9 @@ mod tests { #[test] fn attachment_dims_larger_than_specified_valid() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { color: { load: Clear, @@ -628,20 +646,24 @@ mod tests { color: [color], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let img = AttachmentImage::new(device.clone(), [600, 600], Format::R8G8B8A8Unorm).unwrap(); let _ = Framebuffer::with_dimensions(render_pass, [512, 512, 1]) - .add(img).unwrap() - .build().unwrap(); + .add(img) + .unwrap() + .build() + .unwrap(); } #[test] fn attachment_dims_smaller_than_specified() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { color: { load: Clear, @@ -654,24 +676,29 @@ mod tests { color: [color], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let img = AttachmentImage::new(device.clone(), [512, 700], Format::R8G8B8A8Unorm).unwrap(); match Framebuffer::with_dimensions(render_pass, [600, 600, 1]).add(img) { - Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected, obtained }) => { + Err(FramebufferCreationError::AttachmentDimensionsIncompatible { + expected, + obtained, + }) => { assert_eq!(expected, [600, 600, 1]); assert_eq!(obtained, [512, 700, 1]); }, - _ => panic!() + _ => panic!(), } } #[test] fn multi_attachments_dims_not_identical() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { a: { load: Clear, @@ -690,25 +717,30 @@ mod tests { color: [a, b], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let a = AttachmentImage::new(device.clone(), [512, 512], Format::R8G8B8A8Unorm).unwrap(); let b = AttachmentImage::new(device.clone(), [512, 513], Format::R8G8B8A8Unorm).unwrap(); match Framebuffer::start(render_pass).add(a).unwrap().add(b) { - Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected, obtained }) => { + Err(FramebufferCreationError::AttachmentDimensionsIncompatible { + expected, + obtained, + }) => { assert_eq!(expected, [512, 512, 1]); assert_eq!(obtained, [512, 513, 1]); }, - _ => panic!() + _ => panic!(), } } #[test] fn multi_attachments_auto_smaller() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { a: { load: Clear, @@ -727,27 +759,32 @@ mod tests { color: [a, b], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let a = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(); let b = AttachmentImage::new(device.clone(), [512, 128], Format::R8G8B8A8Unorm).unwrap(); let fb = Framebuffer::with_intersecting_dimensions(render_pass) - .add(a).unwrap() - .add(b).unwrap() - .build().unwrap(); + .add(a) + .unwrap() + .add(b) + .unwrap() + .build() + .unwrap(); match (fb.width(), fb.height(), fb.layers()) { (256, 128, 1) => (), - _ => panic!() + _ => panic!(), } } #[test] fn not_enough_attachments() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { a: { load: Clear, @@ -766,26 +803,31 @@ mod tests { color: [a, b], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let img = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(); let res = Framebuffer::with_intersecting_dimensions(render_pass) - .add(img).unwrap() + .add(img) + .unwrap() .build(); match res { - Err(FramebufferCreationError::AttachmentsCountMismatch { expected: 2, - obtained: 1 }) => (), - _ => panic!() + Err(FramebufferCreationError::AttachmentsCountMismatch { + expected: 2, + obtained: 1, + }) => (), + _ => panic!(), } } #[test] fn too_many_attachments() { let (device, _) = gfx_dev_and_queue!(); - - let render_pass = Arc::new(single_pass_renderpass!(device.clone(), + + let render_pass = Arc::new( + single_pass_renderpass!(device.clone(), attachments: { a: { load: Clear, @@ -798,19 +840,23 @@ mod tests { color: [a], depth_stencil: {} } - ).unwrap()); + ).unwrap(), + ); let a = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(); let b = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(); let res = Framebuffer::with_intersecting_dimensions(render_pass) - .add(a).unwrap() + .add(a) + .unwrap() .add(b); match res { - Err(FramebufferCreationError::AttachmentsCountMismatch { expected: 1, - obtained: 2 }) => (), - _ => panic!() + Err(FramebufferCreationError::AttachmentsCountMismatch { + expected: 1, + obtained: 2, + }) => (), + _ => panic!(), } } @@ -818,19 +864,25 @@ mod tests { fn empty_working() { let (device, _) = gfx_dev_and_queue!(); - let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap(); - let _ = Framebuffer::with_dimensions(rp, [512, 512, 1]).build().unwrap(); + let rp = EmptySinglePassRenderPassDesc + .build_render_pass(device) + .unwrap(); + let _ = Framebuffer::with_dimensions(rp, [512, 512, 1]) + .build() + .unwrap(); } #[test] fn cant_determine_dimensions_auto() { let (device, _) = gfx_dev_and_queue!(); - let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap(); + let rp = EmptySinglePassRenderPassDesc + .build_render_pass(device) + .unwrap(); let res = Framebuffer::start(rp).build(); match res { Err(FramebufferCreationError::CantDetermineDimensions) => (), - _ => panic!() + _ => panic!(), } } @@ -838,11 +890,13 @@ mod tests { fn cant_determine_dimensions_intersect() { let (device, _) = gfx_dev_and_queue!(); - let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap(); + let rp = EmptySinglePassRenderPassDesc + .build_render_pass(device) + .unwrap(); let res = Framebuffer::with_intersecting_dimensions(rp).build(); match res { Err(FramebufferCreationError::CantDetermineDimensions) => (), - _ => panic!() + _ => panic!(), } } } diff --git a/vulkano/src/framebuffer/mod.rs b/vulkano/src/framebuffer/mod.rs index 77315782..83bf083f 100644 --- a/vulkano/src/framebuffer/mod.rs +++ b/vulkano/src/framebuffer/mod.rs @@ -8,11 +8,11 @@ // according to those terms. //! Targets on which your draw commands are executed. -//! +//! //! # Render passes and framebuffers //! //! There are two concepts in Vulkan: -//! +//! //! - A *render pass* describes the target which you are going to render to. It is a collection //! of descriptions of one or more attachments (ie. image that are rendered to), and of one or //! multiples subpasses. The render pass contains the format and number of samples of each @@ -91,17 +91,17 @@ //! pub use self::attachments_list::AttachmentsList; -pub use self::compat_atch::ensure_image_view_compatible; pub use self::compat_atch::IncompatibleRenderPassAttachmentError; +pub use self::compat_atch::ensure_image_view_compatible; pub use self::desc::LayoutAttachmentDescription; -pub use self::desc::LayoutPassDescription; pub use self::desc::LayoutPassDependencyDescription; +pub use self::desc::LayoutPassDescription; +pub use self::desc::LoadOp; pub use self::desc::RenderPassDesc; pub use self::desc::RenderPassDescAttachments; -pub use self::desc::RenderPassDescSubpasses; pub use self::desc::RenderPassDescDependencies; +pub use self::desc::RenderPassDescSubpasses; pub use self::desc::StoreOp; -pub use self::desc::LoadOp; pub use self::empty::EmptySinglePassRenderPassDesc; pub use self::framebuffer::Framebuffer; pub use self::framebuffer::FramebufferBuilder; @@ -111,9 +111,9 @@ pub use self::sys::RenderPass; pub use self::sys::RenderPassCreationError; pub use self::sys::RenderPassSys; pub use self::traits::FramebufferAbstract; -pub use self::traits::RenderPassDescClearValues; -pub use self::traits::RenderPassCompatible; pub use self::traits::RenderPassAbstract; +pub use self::traits::RenderPassCompatible; +pub use self::traits::RenderPassDescClearValues; pub use self::traits::RenderPassSubpassInterface; pub use self::traits::Subpass; diff --git a/vulkano/src/framebuffer/sys.rs b/vulkano/src/framebuffer/sys.rs index c1779290..47bee7b6 100644 --- a/vulkano/src/framebuffer/sys.rs +++ b/vulkano/src/framebuffer/sys.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::marker::PhantomData; @@ -14,7 +15,6 @@ use std::mem; use std::ptr; use std::sync::Arc; use std::sync::Mutex; -use smallvec::SmallVec; use device::Device; use device::DeviceOwned; @@ -24,9 +24,9 @@ use framebuffer::LayoutAttachmentDescription; use framebuffer::LayoutPassDependencyDescription; use framebuffer::LayoutPassDescription; use framebuffer::LoadOp; -use framebuffer::RenderPassDescClearValues; -use framebuffer::RenderPassDesc; use framebuffer::RenderPassAbstract; +use framebuffer::RenderPassDesc; +use framebuffer::RenderPassDescClearValues; use Error; use OomError; @@ -52,7 +52,9 @@ pub struct RenderPass { granularity: Mutex>, } -impl RenderPass where D: RenderPassDesc { +impl RenderPass + where D: RenderPassDesc +{ /// Builds a new render pass. /// /// # Panic @@ -62,42 +64,61 @@ impl RenderPass where D: RenderPassDesc { /// mode. /// pub fn new(device: Arc, description: D) - -> Result, RenderPassCreationError> - { + -> Result, RenderPassCreationError> { let vk = device.pointers(); // If the first use of an attachment in this render pass is as an input attachment, and // the attachment is not also used as a color or depth/stencil attachment in the same // subpass, then loadOp must not be VK_ATTACHMENT_LOAD_OP_CLEAR - debug_assert!(description.attachment_descs().enumerate().all(|(atch_num, attachment)| { + debug_assert!(description.attachment_descs().enumerate().all(|(atch_num, + attachment)| { if attachment.load != LoadOp::Clear { return true; } for p in description.subpass_descs() { - if p.color_attachments.iter().find(|&&(a, _)| a == atch_num).is_some() { return true; } - if let Some((a, _)) = p.depth_stencil { if a == atch_num { return true; } } - if p.input_attachments.iter().find(|&&(a, _)| a == atch_num).is_some() { return false; } + if p.color_attachments + .iter() + .find(|&&(a, _)| a == atch_num) + .is_some() + { + return true; + } + if let Some((a, _)) = p.depth_stencil { + if a == atch_num { + return true; + } + } + if p.input_attachments + .iter() + .find(|&&(a, _)| a == atch_num) + .is_some() + { + return false; + } } true })); - let attachments = description.attachment_descs().map(|attachment| { - debug_assert!(attachment.samples.is_power_of_two()); + let attachments = description + .attachment_descs() + .map(|attachment| { + debug_assert!(attachment.samples.is_power_of_two()); - vk::AttachmentDescription { - flags: 0, // FIXME: may alias flag - format: attachment.format as u32, - samples: attachment.samples, - loadOp: attachment.load as u32, - storeOp: attachment.store as u32, - stencilLoadOp: attachment.stencil_load as u32, - stencilStoreOp: attachment.stencil_store as u32, - initialLayout: attachment.initial_layout as u32, - finalLayout: attachment.final_layout as u32, - } - }).collect::>(); + vk::AttachmentDescription { + flags: 0, // FIXME: may alias flag + format: attachment.format as u32, + samples: attachment.samples, + loadOp: attachment.load as u32, + storeOp: attachment.store as u32, + stencilLoadOp: attachment.stencil_load as u32, + stencilStoreOp: attachment.stencil_store as u32, + initialLayout: attachment.initial_layout as u32, + finalLayout: attachment.final_layout as u32, + } + }) + .collect::>(); // We need to pass pointers to vkAttachmentReference structs when creating the render pass. // Therefore we need to allocate them in advance. @@ -105,71 +126,102 @@ impl RenderPass where D: RenderPassDesc { // This block allocates, for each pass, in order, all color attachment references, then all // input attachment references, then all resolve attachment references, then the depth // stencil attachment reference. - let attachment_references = description.subpass_descs().flat_map(|pass| { - // Performing some validation with debug asserts. - debug_assert!(pass.resolve_attachments.is_empty() || - pass.resolve_attachments.len() == pass.color_attachments.len()); - debug_assert!(pass.resolve_attachments.iter().all(|a| { - attachments[a.0].samples == 1 - })); - debug_assert!(pass.resolve_attachments.is_empty() || - pass.color_attachments.iter().all(|a| { - attachments[a.0].samples > 1 - })); - debug_assert!(pass.resolve_attachments.is_empty() || - pass.resolve_attachments.iter().zip(pass.color_attachments.iter()) - .all(|(r, c)| { - attachments[r.0].format == attachments[c.0].format - })); - debug_assert!(pass.color_attachments.iter().cloned() - .chain(pass.depth_stencil.clone().into_iter()) - .chain(pass.input_attachments.iter().cloned()) - .chain(pass.resolve_attachments.iter().cloned()) - .all(|(a, _)| { - pass.preserve_attachments.iter().find(|&&b| a == b).is_none() - })); - debug_assert!(pass.color_attachments.iter().cloned() - .chain(pass.depth_stencil.clone().into_iter()) - .all(|(atch, layout)| { - if let Some(r) = pass.input_attachments.iter() - .find(|r| r.0 == atch) - { - r.1 == layout - } else { - true - } - })); + let attachment_references = description + .subpass_descs() + .flat_map(|pass| { + // Performing some validation with debug asserts. + debug_assert!(pass.resolve_attachments.is_empty() || + pass.resolve_attachments.len() == pass.color_attachments.len()); + debug_assert!(pass.resolve_attachments + .iter() + .all(|a| attachments[a.0].samples == 1)); + debug_assert!(pass.resolve_attachments.is_empty() || + pass.color_attachments + .iter() + .all(|a| attachments[a.0].samples > 1)); + debug_assert!(pass.resolve_attachments.is_empty() || + pass.resolve_attachments + .iter() + .zip(pass.color_attachments.iter()) + .all(|(r, c)| { + attachments[r.0].format == attachments[c.0].format + })); + debug_assert!(pass.color_attachments + .iter() + .cloned() + .chain(pass.depth_stencil.clone().into_iter()) + .chain(pass.input_attachments.iter().cloned()) + .chain(pass.resolve_attachments.iter().cloned()) + .all(|(a, _)| { + pass.preserve_attachments + .iter() + .find(|&&b| a == b) + .is_none() + })); + debug_assert!( + pass.color_attachments + .iter() + .cloned() + .chain(pass.depth_stencil.clone().into_iter()) + .all(|(atch, layout)| if let Some(r) = + pass.input_attachments.iter().find(|r| r.0 == atch) + { + r.1 == layout + } else { + true + }) + ); - let resolve = pass.resolve_attachments.into_iter().map(|(offset, img_la)| { - debug_assert!(offset < attachments.len()); - vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, } - }); + let resolve = pass.resolve_attachments + .into_iter() + .map(|(offset, img_la)| { + debug_assert!(offset < attachments.len()); + vk::AttachmentReference { + attachment: offset as u32, + layout: img_la as u32, + } + }); - let color = pass.color_attachments.into_iter().map(|(offset, img_la)| { - debug_assert!(offset < attachments.len()); - vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, } - }); + let color = pass.color_attachments.into_iter().map(|(offset, img_la)| { + debug_assert!(offset < attachments.len()); + vk::AttachmentReference { + attachment: offset as u32, + layout: img_la as u32, + } + }); - let input = pass.input_attachments.into_iter().map(|(offset, img_la)| { - debug_assert!(offset < attachments.len()); - vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, } - }); + let input = pass.input_attachments.into_iter().map(|(offset, img_la)| { + debug_assert!(offset < attachments.len()); + vk::AttachmentReference { + attachment: offset as u32, + layout: img_la as u32, + } + }); - let depthstencil = if let Some((offset, img_la)) = pass.depth_stencil { - Some(vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }) - } else { - None - }.into_iter(); + let depthstencil = if let Some((offset, img_la)) = pass.depth_stencil { + Some(vk::AttachmentReference { + attachment: offset as u32, + layout: img_la as u32, + }) + } else { + None + }.into_iter(); - color.chain(input).chain(resolve).chain(depthstencil) - }).collect::>(); + color.chain(input).chain(resolve).chain(depthstencil) + }) + .collect::>(); // Same as `attachment_references` but only for the preserve attachments. // This is separate because attachment references are u32s and not `vkAttachmentReference` // structs. - let preserve_attachments_references = description.subpass_descs().flat_map(|pass| { - pass.preserve_attachments.into_iter().map(|offset| offset as u32) - }).collect::>(); + let preserve_attachments_references = description + .subpass_descs() + .flat_map(|pass| { + pass.preserve_attachments + .into_iter() + .map(|offset| offset as u32) + }) + .collect::>(); // Now iterating over passes. let passes = unsafe { @@ -182,7 +234,7 @@ impl RenderPass where D: RenderPassDesc { for pass in description.subpass_descs() { if pass.color_attachments.len() as u32 > - device.physical_device().limits().max_color_attachments() + device.physical_device().limits().max_color_attachments() { return Err(RenderPassCreationError::ColorAttachmentsLimitExceeded); } @@ -201,26 +253,39 @@ impl RenderPass where D: RenderPassDesc { ptr::null() }; - let preserve_attachments = preserve_attachments_references.as_ptr() - .offset(preserve_ref_index as isize); + let preserve_attachments = preserve_attachments_references + .as_ptr() + .offset(preserve_ref_index as isize); preserve_ref_index += pass.preserve_attachments.len(); out.push(vk::SubpassDescription { - flags: 0, // reserved - pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS, - inputAttachmentCount: pass.input_attachments.len() as u32, - pInputAttachments: if pass.input_attachments.is_empty() { ptr::null() } - else { input_attachments }, - colorAttachmentCount: pass.color_attachments.len() as u32, - pColorAttachments: if pass.color_attachments.is_empty() { ptr::null() } - else { color_attachments }, - pResolveAttachments: if pass.resolve_attachments.is_empty() { ptr::null() } - else { resolve_attachments }, - pDepthStencilAttachment: depth_stencil, - preserveAttachmentCount: pass.preserve_attachments.len() as u32, - pPreserveAttachments: if pass.preserve_attachments.is_empty() { ptr::null() } - else { preserve_attachments }, - }); + flags: 0, // reserved + pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS, + inputAttachmentCount: pass.input_attachments.len() as u32, + pInputAttachments: if pass.input_attachments.is_empty() { + ptr::null() + } else { + input_attachments + }, + colorAttachmentCount: pass.color_attachments.len() as u32, + pColorAttachments: if pass.color_attachments.is_empty() { + ptr::null() + } else { + color_attachments + }, + pResolveAttachments: if pass.resolve_attachments.is_empty() { + ptr::null() + } else { + resolve_attachments + }, + pDepthStencilAttachment: depth_stencil, + preserveAttachmentCount: pass.preserve_attachments.len() as u32, + pPreserveAttachments: if pass.preserve_attachments.is_empty() { + ptr::null() + } else { + preserve_attachments + }, + }); } assert!(!out.is_empty()); @@ -231,48 +296,67 @@ impl RenderPass where D: RenderPassDesc { out }; - let dependencies = description.dependency_descs().map(|dependency| { - debug_assert!(dependency.source_subpass < passes.len()); - debug_assert!(dependency.destination_subpass < passes.len()); + let dependencies = description + .dependency_descs() + .map(|dependency| { + debug_assert!(dependency.source_subpass < passes.len()); + debug_assert!(dependency.destination_subpass < passes.len()); - vk::SubpassDependency { - srcSubpass: dependency.source_subpass as u32, - dstSubpass: dependency.destination_subpass as u32, - srcStageMask: dependency.src_stages.into(), - dstStageMask: dependency.dst_stages.into(), - srcAccessMask: dependency.src_access.into(), - dstAccessMask: dependency.dst_access.into(), - dependencyFlags: if dependency.by_region { vk::DEPENDENCY_BY_REGION_BIT } else { 0 }, - } - }).collect::>(); + vk::SubpassDependency { + srcSubpass: dependency.source_subpass as u32, + dstSubpass: dependency.destination_subpass as u32, + srcStageMask: dependency.src_stages.into(), + dstStageMask: dependency.dst_stages.into(), + srcAccessMask: dependency.src_access.into(), + dstAccessMask: dependency.dst_access.into(), + dependencyFlags: if dependency.by_region { + vk::DEPENDENCY_BY_REGION_BIT + } else { + 0 + }, + } + }) + .collect::>(); let render_pass = unsafe { let infos = vk::RenderPassCreateInfo { sType: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved attachmentCount: attachments.len() as u32, - pAttachments: if attachments.is_empty() { ptr::null() } - else { attachments.as_ptr() }, + pAttachments: if attachments.is_empty() { + ptr::null() + } else { + attachments.as_ptr() + }, subpassCount: passes.len() as u32, - pSubpasses: if passes.is_empty() { ptr::null() } else { passes.as_ptr() }, + pSubpasses: if passes.is_empty() { + ptr::null() + } else { + passes.as_ptr() + }, dependencyCount: dependencies.len() as u32, - pDependencies: if dependencies.is_empty() { ptr::null() } - else { dependencies.as_ptr() }, + pDependencies: if dependencies.is_empty() { + ptr::null() + } else { + dependencies.as_ptr() + }, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateRenderPass(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateRenderPass(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(RenderPass { - device: device.clone(), - render_pass: render_pass, - desc: description, - granularity: Mutex::new(None), - }) + device: device.clone(), + render_pass: render_pass, + desc: description, + granularity: Mutex::new(None), + }) } } @@ -281,9 +365,9 @@ impl RenderPass { /// /// This method is useful for quick tests. #[inline] - pub fn empty_single_pass(device: Arc) - -> Result, RenderPassCreationError> - { + pub fn empty_single_pass( + device: Arc) + -> Result, RenderPassCreationError> { RenderPass::new(device, EmptySinglePassRenderPassDesc) } } @@ -304,8 +388,7 @@ impl RenderPass { unsafe { let vk = self.device.pointers(); let mut out = mem::uninitialized(); - vk.GetRenderAreaGranularity(self.device.internal_object(), - self.render_pass, &mut out); + vk.GetRenderAreaGranularity(self.device.internal_object(), self.render_pass, &mut out); debug_assert_ne!(out.width, 0); debug_assert_ne!(out.height, 0); @@ -325,12 +408,14 @@ impl RenderPass { } } -unsafe impl RenderPassDesc for RenderPass where D: RenderPassDesc { +unsafe impl RenderPassDesc for RenderPass + where D: RenderPassDesc +{ #[inline] fn num_attachments(&self) -> usize { self.desc.num_attachments() } - + #[inline] fn attachment_desc(&self, num: usize) -> Option { self.desc.attachment_desc(num) @@ -340,7 +425,7 @@ unsafe impl RenderPassDesc for RenderPass where D: RenderPassDesc { fn num_subpasses(&self) -> usize { self.desc.num_subpasses() } - + #[inline] fn subpass_desc(&self, num: usize) -> Option { self.desc.subpass_desc(num) @@ -366,7 +451,9 @@ unsafe impl RenderPassDescClearValues for RenderPass } } -unsafe impl RenderPassAbstract for RenderPass where D: RenderPassDesc { +unsafe impl RenderPassAbstract for RenderPass + where D: RenderPassDesc +{ #[inline] fn inner(&self) -> RenderPassSys { RenderPassSys(self.render_pass, PhantomData) @@ -380,7 +467,9 @@ unsafe impl DeviceOwned for RenderPass { } } -impl fmt::Debug for RenderPass where D: fmt::Debug { +impl fmt::Debug for RenderPass + where D: fmt::Debug +{ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt.debug_struct("RenderPass") .field("raw", &self.render_pass) @@ -437,7 +526,7 @@ impl error::Error for RenderPassCreationError { fn cause(&self) -> Option<&error::Error> { match *self { RenderPassCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -466,7 +555,7 @@ impl From for RenderPassCreationError { err @ Error::OutOfDeviceMemory => { RenderPassCreationError::OomError(OomError::from(err)) }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -488,10 +577,11 @@ mod tests { let (device, _) = gfx_dev_and_queue!(); if device.physical_device().limits().max_color_attachments() >= 10 { - return; // test ignored + return; // test ignored } - let rp = single_pass_renderpass! { + let rp = + single_pass_renderpass! { device.clone(), attachments: { a1: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, }, @@ -513,7 +603,7 @@ mod tests { match rp { Err(RenderPassCreationError::ColorAttachmentsLimitExceeded) => (), - _ => panic!() + _ => panic!(), } } diff --git a/vulkano/src/framebuffer/traits.rs b/vulkano/src/framebuffer/traits.rs index c0bf4620..8923fa61 100644 --- a/vulkano/src/framebuffer/traits.rs +++ b/vulkano/src/framebuffer/traits.rs @@ -51,7 +51,10 @@ pub unsafe trait FramebufferAbstract: RenderPassAbstract { } } -unsafe impl FramebufferAbstract for T where T: SafeDeref, T::Target: FramebufferAbstract { +unsafe impl FramebufferAbstract for T + where T: SafeDeref, + T::Target: FramebufferAbstract +{ #[inline] fn inner(&self) -> FramebufferSys { FramebufferAbstract::inner(&**self) @@ -99,7 +102,10 @@ pub unsafe trait RenderPassAbstract: DeviceOwned + RenderPassDesc { fn inner(&self) -> RenderPassSys; } -unsafe impl RenderPassAbstract for T where T: SafeDeref, T::Target: RenderPassAbstract { +unsafe impl RenderPassAbstract for T + where T: SafeDeref, + T::Target: RenderPassAbstract +{ #[inline] fn inner(&self) -> RenderPassSys { (**self).inner() @@ -137,7 +143,8 @@ pub unsafe trait RenderPassDescClearValues { } unsafe impl RenderPassDescClearValues for T - where T: SafeDeref, T::Target: RenderPassDescClearValues + where T: SafeDeref, + T::Target: RenderPassDescClearValues { #[inline] fn convert_clear_values(&self, vals: C) -> Box> { @@ -164,10 +171,13 @@ pub unsafe trait RenderPassSubpassInterface: RenderPassDesc } unsafe impl RenderPassSubpassInterface for A - where A: RenderPassDesc, B: ShaderInterfaceDef + where A: RenderPassDesc, + B: ShaderInterfaceDef { fn is_compatible_with(&self, subpass: u32, other: &B) -> bool { - let pass_descr = match RenderPassDesc::subpass_descs(self).skip(subpass as usize).next() { + let pass_descr = match RenderPassDesc::subpass_descs(self) + .skip(subpass as usize) + .next() { Some(s) => s, None => return false, }; @@ -179,7 +189,11 @@ unsafe impl RenderPassSubpassInterface for A None => return false, }; - let attachment_desc = (&self).attachment_descs().skip(attachment_id).next().unwrap(); + let attachment_desc = (&self) + .attachment_descs() + .skip(attachment_id) + .next() + .unwrap(); // FIXME: compare formats depending on the number of components and data type /*if attachment_desc.format != element.format { @@ -201,7 +215,9 @@ unsafe impl RenderPassSubpassInterface for A // TODO: once specialization lands, this trait can be specialized for pairs that are known to // always be compatible // TODO: maybe this can be unimplemented on some pairs, to provide compile-time checks? -pub unsafe trait RenderPassCompatible: RenderPassDesc where Other: RenderPassDesc { +pub unsafe trait RenderPassCompatible: RenderPassDesc + where Other: RenderPassDesc +{ /// Returns `true` if this layout is compatible with the other layout, as defined in the /// `Render Pass Compatibility` section of the Vulkan specs. // TODO: return proper error @@ -209,7 +225,8 @@ pub unsafe trait RenderPassCompatible: RenderPassDesc where Other } unsafe impl RenderPassCompatible for A - where A: RenderPassDesc, B: RenderPassDesc + where A: RenderPassDesc, + B: RenderPassDesc { fn is_compatible_with(&self, other: &B) -> bool { // FIXME: @@ -237,15 +254,17 @@ pub struct Subpass { subpass_id: u32, } -impl Subpass where L: RenderPassDesc { +impl Subpass + where L: RenderPassDesc +{ /// Returns a handle that represents a subpass of a render pass. #[inline] pub fn from(render_pass: L, id: u32) -> Option> { if (id as usize) < render_pass.num_subpasses() { Some(Subpass { - render_pass: render_pass, - subpass_id: id, - }) + render_pass: render_pass, + subpass_id: id, + }) } else { None @@ -255,7 +274,9 @@ impl Subpass where L: RenderPassDesc { /// Returns the number of color attachments in this subpass. #[inline] pub fn num_color_attachments(&self) -> u32 { - self.render_pass.num_color_attachments(self.subpass_id).unwrap() + self.render_pass + .num_color_attachments(self.subpass_id) + .unwrap() } /// Returns true if the subpass has a depth attachment or a depth-stencil attachment. @@ -268,7 +289,9 @@ impl Subpass where L: RenderPassDesc { /// layout is not `DepthStencilReadOnlyOptimal`. #[inline] pub fn has_writable_depth(&self) -> bool { - self.render_pass.has_writable_depth(self.subpass_id).unwrap() + self.render_pass + .has_writable_depth(self.subpass_id) + .unwrap() } /// Returns true if the subpass has a stencil attachment or a depth-stencil attachment. @@ -281,14 +304,18 @@ impl Subpass where L: RenderPassDesc { /// layout is not `DepthStencilReadOnlyOptimal`. #[inline] pub fn has_writable_stencil(&self) -> bool { - self.render_pass.has_writable_stencil(self.subpass_id).unwrap() + self.render_pass + .has_writable_stencil(self.subpass_id) + .unwrap() } /// Returns true if the subpass has any color or depth/stencil attachment. #[inline] pub fn has_color_or_depth_stencil_attachment(&self) -> bool { self.num_color_attachments() >= 1 || - self.render_pass.has_depth_stencil_attachment(self.subpass_id).unwrap() != (false, false) + self.render_pass + .has_depth_stencil_attachment(self.subpass_id) + .unwrap() != (false, false) } /// Returns the number of samples in the color and/or depth/stencil attachments. Returns `None` diff --git a/vulkano/src/image/attachment.rs b/vulkano/src/image/attachment.rs index 942c35d5..fb34facb 100644 --- a/vulkano/src/image/attachment.rs +++ b/vulkano/src/image/attachment.rs @@ -21,10 +21,10 @@ use format::FormatDesc; use format::FormatTy; use image::Dimensions; use image::ImageDimensions; -use image::ViewType; -use image::sys::ImageCreationError; use image::ImageLayout; use image::ImageUsage; +use image::ViewType; +use image::sys::ImageCreationError; use image::sys::UnsafeImage; use image::sys::UnsafeImageView; use image::traits::ImageAccess; @@ -147,7 +147,7 @@ impl AttachmentImage { { let base_usage = ImageUsage { transient_attachment: true, - .. ImageUsage::none() + ..ImageUsage::none() }; AttachmentImage::new_impl(device, dimensions, format, base_usage, 1) @@ -158,20 +158,22 @@ impl AttachmentImage { /// > **Note**: You can also use this function and pass `1` for the number of samples if you /// > want a regular image. #[inline] - pub fn transient_multisampled(device: Arc, dimensions: [u32; 2], samples: u32, format: F) + pub fn transient_multisampled(device: Arc, dimensions: [u32; 2], samples: u32, + format: F) -> Result>, ImageCreationError> where F: FormatDesc { let base_usage = ImageUsage { transient_attachment: true, - .. ImageUsage::none() + ..ImageUsage::none() }; AttachmentImage::new_impl(device, dimensions, format, base_usage, samples) } fn new_impl(device: Arc, dimensions: [u32; 2], format: F, base_usage: ImageUsage, - samples: u32) -> Result>, ImageCreationError> + samples: u32) + -> Result>, ImageCreationError> where F: FormatDesc { // TODO: check dimensions against the max_framebuffer_width/height/layers limits @@ -181,13 +183,13 @@ impl AttachmentImage { FormatTy::DepthStencil => true, FormatTy::Stencil => true, FormatTy::Compressed => panic!(), - _ => false + _ => false, }; let usage = ImageUsage { color_attachment: !is_depth, depth_stencil_attachment: is_depth, - .. base_usage + ..base_usage }; let (image, mem_reqs) = unsafe { @@ -195,40 +197,57 @@ impl AttachmentImage { width: dimensions[0], height: dimensions[1], array_layers: 1, - cubemap_compatible: false + cubemap_compatible: false, }; - try!(UnsafeImage::new(device.clone(), usage, format.format(), dims, - samples, 1, Sharing::Exclusive::>, false, false)) + UnsafeImage::new(device.clone(), + usage, + format.format(), + dims, + samples, + 1, + Sharing::Exclusive::>, + false, + false)? }; let mem_ty = { - let device_local = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_device_local()); - let any = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); + let device_local = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_device_local()); + let any = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); device_local.chain(any).next().unwrap() }; - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Optimal)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Optimal)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); - unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); } + unsafe { + image.bind_memory(mem.memory(), mem.offset())?; + } - let view = unsafe { - try!(UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1)) - }; + let view = unsafe { UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1)? }; Ok(Arc::new(AttachmentImage { - image: image, - view: view, - memory: mem, - format: format, - attachment_layout: if is_depth { ImageLayout::DepthStencilAttachmentOptimal } - else { ImageLayout::ColorAttachmentOptimal }, - gpu_lock: AtomicUsize::new(0), - })) + image: image, + view: view, + memory: mem, + format: format, + attachment_layout: if is_depth { + ImageLayout::DepthStencilAttachmentOptimal + } else { + ImageLayout::ColorAttachmentOptimal + }, + gpu_lock: AtomicUsize::new(0), + })) } } @@ -300,7 +319,7 @@ unsafe impl ImageContent

for Arc> { #[inline] fn matches_format(&self) -> bool { - true // FIXME: + true // FIXME: } } @@ -315,7 +334,10 @@ unsafe impl ImageViewAccess for AttachmentImage #[inline] fn dimensions(&self) -> Dimensions { let dims = self.image.dimensions(); - Dimensions::Dim2d { width: dims.width(), height: dims.height() } + Dimensions::Dim2d { + width: dims.width(), + height: dims.height(), + } } #[inline] diff --git a/vulkano/src/image/immutable.rs b/vulkano/src/image/immutable.rs index 726991a1..e2308775 100644 --- a/vulkano/src/image/immutable.rs +++ b/vulkano/src/image/immutable.rs @@ -7,8 +7,8 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; use smallvec::SmallVec; +use std::sync::Arc; use device::Device; use device::Queue; @@ -16,10 +16,10 @@ use format::Format; use format::FormatDesc; use image::Dimensions; use image::ImageDimensions; -use image::MipmapsCount; -use image::sys::ImageCreationError; use image::ImageLayout; use image::ImageUsage; +use image::MipmapsCount; +use image::sys::ImageCreationError; use image::sys::UnsafeImage; use image::sys::UnsafeImageView; use image::traits::ImageAccess; @@ -37,7 +37,9 @@ use sync::Sharing; /// but then you must only ever read from it. TODO: clarify because of blit operations // TODO: type (2D, 3D, array, etc.) as template parameter #[derive(Debug)] -pub struct ImmutableImage> where A: MemoryPool { +pub struct ImmutableImage> + where A: MemoryPool +{ image: UnsafeImage, view: UnsafeImageView, dimensions: Dimensions, @@ -51,26 +53,35 @@ impl ImmutableImage { #[inline] pub fn new<'a, I>(device: Arc, dimensions: Dimensions, format: F, queue_families: I) -> Result>, ImageCreationError> - where F: FormatDesc, I: IntoIterator> + where F: FormatDesc, + I: IntoIterator> { - ImmutableImage::with_mipmaps(device, dimensions, format, MipmapsCount::One, queue_families) + ImmutableImage::with_mipmaps(device, + dimensions, + format, + MipmapsCount::One, + queue_families) } /// Builds a new immutable image with the given number of mipmaps. pub fn with_mipmaps<'a, I, M>(device: Arc, dimensions: Dimensions, format: F, mipmaps: M, queue_families: I) -> Result>, ImageCreationError> - where F: FormatDesc, I: IntoIterator>, M: Into + where F: FormatDesc, + I: IntoIterator>, + M: Into { let usage = ImageUsage { - transfer_source: true, // for blits + transfer_source: true, // for blits transfer_dest: true, sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; - let queue_families = queue_families.into_iter().map(|f| f.id()) - .collect::>(); + let queue_families = queue_families + .into_iter() + .map(|f| f.id()) + .collect::>(); let (image, mem_reqs) = unsafe { let sharing = if queue_families.len() >= 2 { @@ -79,40 +90,60 @@ impl ImmutableImage { Sharing::Exclusive }; - try!(UnsafeImage::new(device.clone(), usage, format.format(), dimensions.to_image_dimensions(), - 1, mipmaps, sharing, false, false)) + UnsafeImage::new(device.clone(), + usage, + format.format(), + dimensions.to_image_dimensions(), + 1, + mipmaps, + sharing, + false, + false)? }; let mem_ty = { - let device_local = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_device_local()); - let any = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); + let device_local = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_device_local()); + let any = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); device_local.chain(any).next().unwrap() }; - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Optimal)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Optimal)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); - unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); } + unsafe { + image.bind_memory(mem.memory(), mem.offset())?; + } let view = unsafe { - try!(UnsafeImageView::raw(&image, dimensions.to_view_type(), 0 .. image.mipmap_levels(), - 0 .. image.dimensions().array_layers())) + UnsafeImageView::raw(&image, + dimensions.to_view_type(), + 0 .. image.mipmap_levels(), + 0 .. image.dimensions().array_layers())? }; Ok(Arc::new(ImmutableImage { - image: image, - view: view, - memory: mem, - dimensions: dimensions, - format: format, - })) + image: image, + view: view, + memory: mem, + dimensions: dimensions, + format: format, + })) } } -impl ImmutableImage where A: MemoryPool { +impl ImmutableImage + where A: MemoryPool +{ /// Returns the dimensions of the image. #[inline] pub fn dimensions(&self) -> Dimensions { @@ -126,7 +157,10 @@ impl ImmutableImage where A: MemoryPool { } } -unsafe impl ImageAccess for ImmutableImage where F: 'static + Send + Sync, A: MemoryPool { +unsafe impl ImageAccess for ImmutableImage + where F: 'static + Send + Sync, + A: MemoryPool +{ #[inline] fn inner(&self) -> &UnsafeImage { &self.image @@ -134,12 +168,12 @@ unsafe impl ImageAccess for ImmutableImage where F: 'static + Send + #[inline] fn initial_layout_requirement(&self) -> ImageLayout { - ImageLayout::ShaderReadOnlyOptimal // TODO: ? + ImageLayout::ShaderReadOnlyOptimal // TODO: ? } #[inline] fn final_layout_requirement(&self) -> ImageLayout { - ImageLayout::ShaderReadOnlyOptimal // TODO: ? + ImageLayout::ShaderReadOnlyOptimal // TODO: ? } #[inline] @@ -149,7 +183,7 @@ unsafe impl ImageAccess for ImmutableImage where F: 'static + Send + #[inline] fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> { - Ok(()) // FIXME: + Ok(()) // FIXME: } #[inline] @@ -164,16 +198,18 @@ unsafe impl ImageAccess for ImmutableImage where F: 'static + Send + } unsafe impl ImageContent

for ImmutableImage - where F: 'static + Send + Sync, A: MemoryPool + where F: 'static + Send + Sync, + A: MemoryPool { #[inline] fn matches_format(&self) -> bool { - true // FIXME: + true // FIXME: } } unsafe impl ImageViewAccess for ImmutableImage - where F: 'static + Send + Sync, A: MemoryPool + where F: 'static + Send + Sync, + A: MemoryPool { #[inline] fn parent(&self) -> &ImageAccess { diff --git a/vulkano/src/image/mod.rs b/vulkano/src/image/mod.rs index 6eba790c..cce59349 100644 --- a/vulkano/src/image/mod.rs +++ b/vulkano/src/image/mod.rs @@ -8,7 +8,7 @@ // according to those terms. //! Images storage (1D, 2D, 3D, arrays, etc.). -//! +//! //! An *image* is a location in memory whose purpose is to store multi-dimensional data. Its //! most common usage is to store a 2D array of color pixels (in other words an *image* in the //! everyday language), but it can also be used to store arbitrary data. @@ -56,11 +56,11 @@ pub use self::traits::ImageAccess; pub use self::traits::ImageViewAccess; pub use self::usage::ImageUsage; -pub mod attachment; // TODO: make private -pub mod immutable; // TODO: make private +pub mod attachment; // TODO: make private +pub mod immutable; // TODO: make private mod layout; mod storage; -pub mod swapchain; // TODO: make private +pub mod swapchain; // TODO: make private pub mod sys; pub mod traits; mod usage; @@ -144,7 +144,11 @@ pub enum Dimensions { Dim1d { width: u32 }, Dim1dArray { width: u32, array_layers: u32 }, Dim2d { width: u32, height: u32 }, - Dim2dArray { width: u32, height: u32, array_layers: u32 }, + Dim2dArray { + width: u32, + height: u32, + array_layers: u32, + }, Dim3d { width: u32, height: u32, depth: u32 }, Cubemap { size: u32 }, CubemapArray { size: u32, array_layers: u32 }, @@ -171,7 +175,7 @@ impl Dimensions { Dimensions::Dim1dArray { .. } => 1, Dimensions::Dim2d { height, .. } => height, Dimensions::Dim2dArray { height, .. } => height, - Dimensions::Dim3d { height, .. } => height, + Dimensions::Dim3d { height, .. } => height, Dimensions::Cubemap { size } => size, Dimensions::CubemapArray { size, .. } => size, } @@ -189,7 +193,7 @@ impl Dimensions { Dimensions::Dim1dArray { .. } => 1, Dimensions::Dim2d { .. } => 1, Dimensions::Dim2dArray { .. } => 1, - Dimensions::Dim3d { depth, .. } => depth, + Dimensions::Dim3d { depth, .. } => depth, Dimensions::Cubemap { .. } => 1, Dimensions::CubemapArray { .. } => 1, } @@ -207,7 +211,7 @@ impl Dimensions { Dimensions::Dim1dArray { array_layers, .. } => array_layers, Dimensions::Dim2d { .. } => 1, Dimensions::Dim2dArray { array_layers, .. } => array_layers, - Dimensions::Dim3d { .. } => 1, + Dimensions::Dim3d { .. } => 1, Dimensions::Cubemap { .. } => 1, Dimensions::CubemapArray { array_layers, .. } => array_layers, } @@ -220,7 +224,7 @@ impl Dimensions { Dimensions::Dim1dArray { array_layers, .. } => array_layers, Dimensions::Dim2d { .. } => 1, Dimensions::Dim2dArray { array_layers, .. } => array_layers, - Dimensions::Dim3d { .. } => 1, + Dimensions::Dim3d { .. } => 1, Dimensions::Cubemap { .. } => 6, Dimensions::CubemapArray { array_layers, .. } => array_layers * 6, } @@ -231,29 +235,66 @@ impl Dimensions { pub fn to_image_dimensions(&self) -> ImageDimensions { match *self { Dimensions::Dim1d { width } => { - ImageDimensions::Dim1d { width: width, array_layers: 1 } + ImageDimensions::Dim1d { + width: width, + array_layers: 1, + } }, - Dimensions::Dim1dArray { width, array_layers } => { - ImageDimensions::Dim1d { width: width, array_layers: array_layers } + Dimensions::Dim1dArray { + width, + array_layers, + } => { + ImageDimensions::Dim1d { + width: width, + array_layers: array_layers, + } }, Dimensions::Dim2d { width, height } => { - ImageDimensions::Dim2d { width: width, height: height, array_layers: 1, - cubemap_compatible: false } + ImageDimensions::Dim2d { + width: width, + height: height, + array_layers: 1, + cubemap_compatible: false, + } }, - Dimensions::Dim2dArray { width, height, array_layers } => { - ImageDimensions::Dim2d { width: width, height: height, - array_layers: array_layers, cubemap_compatible: false } + Dimensions::Dim2dArray { + width, + height, + array_layers, + } => { + ImageDimensions::Dim2d { + width: width, + height: height, + array_layers: array_layers, + cubemap_compatible: false, + } }, - Dimensions::Dim3d { width, height, depth } => { - ImageDimensions::Dim3d { width: width, height: height, depth: depth } + Dimensions::Dim3d { + width, + height, + depth, + } => { + ImageDimensions::Dim3d { + width: width, + height: height, + depth: depth, + } }, Dimensions::Cubemap { size } => { - ImageDimensions::Dim2d { width: size, height: size, array_layers: 6, - cubemap_compatible: true } + ImageDimensions::Dim2d { + width: size, + height: size, + array_layers: 6, + cubemap_compatible: true, + } }, Dimensions::CubemapArray { size, array_layers } => { - ImageDimensions::Dim2d { width: size, height: size, array_layers: array_layers * 6, - cubemap_compatible: true } + ImageDimensions::Dim2d { + width: size, + height: size, + array_layers: array_layers * 6, + cubemap_compatible: true, + } }, } } @@ -287,8 +328,13 @@ pub enum ViewType { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ImageDimensions { Dim1d { width: u32, array_layers: u32 }, - Dim2d { width: u32, height: u32, array_layers: u32, cubemap_compatible: bool }, - Dim3d { width: u32, height: u32, depth: u32 } + Dim2d { + width: u32, + height: u32, + array_layers: u32, + cubemap_compatible: bool, + }, + Dim3d { width: u32, height: u32, depth: u32 }, } impl ImageDimensions { @@ -297,7 +343,7 @@ impl ImageDimensions { match *self { ImageDimensions::Dim1d { width, .. } => width, ImageDimensions::Dim2d { width, .. } => width, - ImageDimensions::Dim3d { width, .. } => width, + ImageDimensions::Dim3d { width, .. } => width, } } @@ -306,7 +352,7 @@ impl ImageDimensions { match *self { ImageDimensions::Dim1d { .. } => 1, ImageDimensions::Dim2d { height, .. } => height, - ImageDimensions::Dim3d { height, .. } => height, + ImageDimensions::Dim3d { height, .. } => height, } } @@ -320,7 +366,7 @@ impl ImageDimensions { match *self { ImageDimensions::Dim1d { .. } => 1, ImageDimensions::Dim2d { .. } => 1, - ImageDimensions::Dim3d { depth, .. } => depth, + ImageDimensions::Dim3d { depth, .. } => depth, } } @@ -334,7 +380,7 @@ impl ImageDimensions { match *self { ImageDimensions::Dim1d { array_layers, .. } => array_layers, ImageDimensions::Dim2d { array_layers, .. } => array_layers, - ImageDimensions::Dim3d { .. } => 1, + ImageDimensions::Dim3d { .. } => 1, } } } diff --git a/vulkano/src/image/storage.rs b/vulkano/src/image/storage.rs index 055c2021..d27bd32d 100644 --- a/vulkano/src/image/storage.rs +++ b/vulkano/src/image/storage.rs @@ -7,23 +7,23 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::iter::Empty; use std::sync::Arc; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; -use smallvec::SmallVec; use device::Device; use device::Queue; use format::ClearValue; +use format::Format; use format::FormatDesc; use format::FormatTy; -use format::Format; use image::Dimensions; use image::ImageDimensions; -use image::sys::ImageCreationError; use image::ImageLayout; use image::ImageUsage; +use image::sys::ImageCreationError; use image::sys::UnsafeImage; use image::sys::UnsafeImageView; use image::traits::ImageAccess; @@ -41,7 +41,9 @@ use sync::Sharing; /// General-purpose image in device memory. Can be used for any usage, but will be slower than a /// specialized image. #[derive(Debug)] -pub struct StorageImage> where A: MemoryPool { +pub struct StorageImage> + where A: MemoryPool +{ // Inner implementation. image: UnsafeImage, @@ -69,14 +71,14 @@ impl StorageImage { pub fn new<'a, I>(device: Arc, dimensions: Dimensions, format: F, queue_families: I) -> Result>, ImageCreationError> where F: FormatDesc, - I: IntoIterator> + I: IntoIterator> { let is_depth = match format.format().ty() { FormatTy::Depth => true, FormatTy::DepthStencil => true, FormatTy::Stencil => true, FormatTy::Compressed => panic!(), - _ => false + _ => false, }; let usage = ImageUsage { @@ -90,8 +92,10 @@ impl StorageImage { transient_attachment: false, }; - let queue_families = queue_families.into_iter().map(|f| f.id()) - .collect::>(); + let queue_families = queue_families + .into_iter() + .map(|f| f.id()) + .collect::>(); let (image, mem_reqs) = unsafe { let sharing = if queue_families.len() >= 2 { @@ -100,42 +104,62 @@ impl StorageImage { Sharing::Exclusive }; - try!(UnsafeImage::new(device.clone(), usage, format.format(), dimensions.to_image_dimensions(), - 1, 1, Sharing::Exclusive::>, false, false)) + UnsafeImage::new(device.clone(), + usage, + format.format(), + dimensions.to_image_dimensions(), + 1, + 1, + Sharing::Exclusive::>, + false, + false)? }; let mem_ty = { - let device_local = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) - .filter(|t| t.is_device_local()); - let any = device.physical_device().memory_types() - .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); + let device_local = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0) + .filter(|t| t.is_device_local()); + let any = device + .physical_device() + .memory_types() + .filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0); device_local.chain(any).next().unwrap() }; - let mem = try!(MemoryPool::alloc(&Device::standard_pool(&device), mem_ty, - mem_reqs.size, mem_reqs.alignment, AllocLayout::Optimal)); + let mem = MemoryPool::alloc(&Device::standard_pool(&device), + mem_ty, + mem_reqs.size, + mem_reqs.alignment, + AllocLayout::Optimal)?; debug_assert!((mem.offset() % mem_reqs.alignment) == 0); - unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); } + unsafe { + image.bind_memory(mem.memory(), mem.offset())?; + } let view = unsafe { - try!(UnsafeImageView::raw(&image, dimensions.to_view_type(), 0 .. image.mipmap_levels(), - 0 .. image.dimensions().array_layers())) + UnsafeImageView::raw(&image, + dimensions.to_view_type(), + 0 .. image.mipmap_levels(), + 0 .. image.dimensions().array_layers())? }; Ok(Arc::new(StorageImage { - image: image, - view: view, - memory: mem, - dimensions: dimensions, - format: format, - queue_families: queue_families, - gpu_lock: AtomicUsize::new(0), - })) + image: image, + view: view, + memory: mem, + dimensions: dimensions, + format: format, + queue_families: queue_families, + gpu_lock: AtomicUsize::new(0), + })) } } -impl StorageImage where A: MemoryPool { +impl StorageImage + where A: MemoryPool +{ /// Returns the dimensions of the image. #[inline] pub fn dimensions(&self) -> Dimensions { @@ -143,7 +167,10 @@ impl StorageImage where A: MemoryPool { } } -unsafe impl ImageAccess for StorageImage where F: 'static + Send + Sync, A: MemoryPool { +unsafe impl ImageAccess for StorageImage + where F: 'static + Send + Sync, + A: MemoryPool +{ #[inline] fn inner(&self) -> &UnsafeImage { &self.image @@ -188,7 +215,8 @@ unsafe impl ImageAccess for StorageImage where F: 'static + Send + S } unsafe impl ImageClearValue for StorageImage - where F: FormatDesc + 'static + Send + Sync, A: MemoryPool + where F: FormatDesc + 'static + Send + Sync, + A: MemoryPool { #[inline] fn decode(&self, value: F::ClearValue) -> Option { @@ -197,16 +225,18 @@ unsafe impl ImageClearValue for StorageImage } unsafe impl ImageContent

for StorageImage - where F: 'static + Send + Sync, A: MemoryPool + where F: 'static + Send + Sync, + A: MemoryPool { #[inline] fn matches_format(&self) -> bool { - true // FIXME: + true // FIXME: } } unsafe impl ImageViewAccess for StorageImage - where F: 'static + Send + Sync, A: MemoryPool + where F: 'static + Send + Sync, + A: MemoryPool { #[inline] fn parent(&self) -> &ImageAccess { @@ -258,7 +288,13 @@ mod tests { #[test] fn create() { let (device, queue) = gfx_dev_and_queue!(); - let _img = StorageImage::new(device, Dimensions::Dim2d { width: 32, height: 32 }, - Format::R8G8B8A8Unorm, Some(queue.family())).unwrap(); + let _img = StorageImage::new(device, + Dimensions::Dim2d { + width: 32, + height: 32, + }, + Format::R8G8B8A8Unorm, + Some(queue.family())) + .unwrap(); } } diff --git a/vulkano/src/image/swapchain.rs b/vulkano/src/image/swapchain.rs index 07e974c1..75e3abe3 100644 --- a/vulkano/src/image/swapchain.rs +++ b/vulkano/src/image/swapchain.rs @@ -13,16 +13,16 @@ use device::Queue; use format::ClearValue; use format::Format; use format::FormatDesc; -use image::ImageDimensions; use image::Dimensions; +use image::ImageDimensions; +use image::ImageLayout; use image::ViewType; +use image::sys::UnsafeImage; +use image::sys::UnsafeImageView; use image::traits::ImageAccess; use image::traits::ImageClearValue; use image::traits::ImageContent; use image::traits::ImageViewAccess; -use image::ImageLayout; -use image::sys::UnsafeImage; -use image::sys::UnsafeImageView; use swapchain::Swapchain; use sync::AccessError; @@ -53,16 +53,15 @@ impl SwapchainImage { /// /// This is an internal method that you shouldn't call. pub unsafe fn from_raw(swapchain: Arc, id: usize) - -> Result, OomError> - { + -> Result, OomError> { let image = swapchain.raw_image(id).unwrap(); - let view = try!(UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1)); + let view = UnsafeImageView::raw(&image, ViewType::Dim2d, 0 .. 1, 0 .. 1)?; Ok(Arc::new(SwapchainImage { - swapchain: swapchain.clone(), - image_offset: id, - view: view, - })) + swapchain: swapchain.clone(), + image_offset: id, + view: view, + })) } /// Returns the dimensions of the image. @@ -122,8 +121,7 @@ unsafe impl ImageAccess for SwapchainImage { } } -unsafe impl ImageClearValue<::ClearValue> for SwapchainImage -{ +unsafe impl ImageClearValue<::ClearValue> for SwapchainImage { #[inline] fn decode(&self, value: ::ClearValue) -> Option { Some(self.swapchain.format().decode_clear_value(value)) @@ -133,7 +131,7 @@ unsafe impl ImageClearValue<::ClearValue> for SwapchainIma unsafe impl

ImageContent

for SwapchainImage { #[inline] fn matches_format(&self) -> bool { - true // FIXME: + true // FIXME: } } @@ -146,7 +144,10 @@ unsafe impl ImageViewAccess for SwapchainImage { #[inline] fn dimensions(&self) -> Dimensions { let dims = self.swapchain.dimensions(); - Dimensions::Dim2d { width: dims[0], height: dims[1] } + Dimensions::Dim2d { + width: dims[0], + height: dims[1], + } } #[inline] diff --git a/vulkano/src/image/sys.rs b/vulkano/src/image/sys.rs index 4875ed84..c8c82249 100644 --- a/vulkano/src/image/sys.rs +++ b/vulkano/src/image/sys.rs @@ -13,13 +13,13 @@ //! other image or image view types of this library, and all custom image or image view types //! that you create must wrap around the types in this module. +use smallvec::SmallVec; use std::error; use std::fmt; use std::mem; use std::ops::Range; use std::ptr; use std::sync::Arc; -use smallvec::SmallVec; use device::Device; use format::Format; @@ -83,15 +83,23 @@ impl UnsafeImage { sharing: Sharing, linear_tiling: bool, preinitialized_layout: bool) -> Result<(UnsafeImage, MemoryRequirements), ImageCreationError> - where Mi: Into, I: Iterator + where Mi: Into, + I: Iterator { let sharing = match sharing { Sharing::Exclusive => (vk::SHARING_MODE_EXCLUSIVE, SmallVec::<[u32; 8]>::new()), Sharing::Concurrent(ids) => (vk::SHARING_MODE_CONCURRENT, ids.collect()), }; - UnsafeImage::new_impl(device, usage, format, dimensions, num_samples, mipmaps.into(), - sharing, linear_tiling, preinitialized_layout) + UnsafeImage::new_impl(device, + usage, + format, + dimensions, + num_samples, + mipmaps.into(), + sharing, + linear_tiling, + preinitialized_layout) } // Non-templated version to avoid inlining and improve compile times. @@ -99,8 +107,7 @@ impl UnsafeImage { dimensions: ImageDimensions, num_samples: u32, mipmaps: MipmapsCount, (sh_mode, sh_indices): (vk::SharingMode, SmallVec<[u32; 8]>), linear_tiling: bool, preinitialized_layout: bool) - -> Result<(UnsafeImage, MemoryRequirements), ImageCreationError> - { + -> Result<(UnsafeImage, MemoryRequirements), ImageCreationError> { // TODO: doesn't check that the proper features are enabled let vk = device.pointers(); @@ -132,17 +139,27 @@ impl UnsafeImage { if usage.color_attachment && (features & vk::FORMAT_FEATURE_COLOR_ATTACHMENT_BIT == 0) { return Err(ImageCreationError::UnsupportedUsage); } - if usage.depth_stencil_attachment && (features & vk::FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT == 0) { + if usage.depth_stencil_attachment && + (features & vk::FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT == 0) + { return Err(ImageCreationError::UnsupportedUsage); } - if usage.input_attachment && (features & (vk::FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) { + if usage.input_attachment && + (features & + (vk::FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | + vk::FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) + { return Err(ImageCreationError::UnsupportedUsage); } if device.loaded_extensions().khr_maintenance1 { - if usage.transfer_source && (features & vk::FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR == 0) { + if usage.transfer_source && + (features & vk::FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR == 0) + { return Err(ImageCreationError::UnsupportedUsage); } - if usage.transfer_dest && (features & vk::FORMAT_FEATURE_TRANSFER_DST_BIT_KHR == 0) { + if usage.transfer_dest && + (features & vk::FORMAT_FEATURE_TRANSFER_DST_BIT_KHR == 0) + { return Err(ImageCreationError::UnsupportedUsage); } } @@ -158,7 +175,7 @@ impl UnsafeImage { color_attachment: false, depth_stencil_attachment: false, input_attachment: false, - .. usage.clone() + ..usage.clone() }; if u != ImageUsage::none() { @@ -181,7 +198,11 @@ impl UnsafeImage { ImageDimensions::Dim2d { width, height, .. } => { if width < height { width } else { height } }, - ImageDimensions::Dim3d { width, height, depth } => { + ImageDimensions::Dim3d { + width, + height, + depth, + } => { if width < height { if depth < width { depth } else { width } } else { @@ -198,12 +219,14 @@ impl UnsafeImage { MipmapsCount::Specific(num) => { if num < 1 { return Err(ImageCreationError::InvalidMipmapsCount { - obtained: num, valid_range: 1 .. max_mipmaps + 1 - }); + obtained: num, + valid_range: 1 .. max_mipmaps + 1, + }); } else if num > max_mipmaps { capabilities_error = Some(ImageCreationError::InvalidMipmapsCount { - obtained: num, valid_range: 1 .. max_mipmaps + 1 - }); + obtained: num, + valid_range: 1 .. max_mipmaps + 1, + }); } num @@ -220,61 +243,85 @@ impl UnsafeImage { return Err(ImageCreationError::UnsupportedSamplesCount { obtained: num_samples }); } else { - let mut supported_samples = 0x7f; // all bits up to VK_SAMPLE_COUNT_64_BIT + let mut supported_samples = 0x7f; // all bits up to VK_SAMPLE_COUNT_64_BIT if usage.sampled { match format.ty() { FormatTy::Float | FormatTy::Compressed => { - supported_samples &= device.physical_device().limits() - .sampled_image_color_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_color_sample_counts(); }, FormatTy::Uint | FormatTy::Sint => { - supported_samples &= device.physical_device().limits() - .sampled_image_integer_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_integer_sample_counts(); }, FormatTy::Depth => { - supported_samples &= device.physical_device().limits() - .sampled_image_depth_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_depth_sample_counts(); }, FormatTy::Stencil => { - supported_samples &= device.physical_device().limits() - .sampled_image_stencil_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_stencil_sample_counts(); }, FormatTy::DepthStencil => { - supported_samples &= device.physical_device().limits() - .sampled_image_depth_sample_counts(); - supported_samples &= device.physical_device().limits() - .sampled_image_stencil_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_depth_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .sampled_image_stencil_sample_counts(); }, } } if usage.storage { - supported_samples &= device.physical_device().limits() - .storage_image_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .storage_image_sample_counts(); } - if usage.color_attachment || usage.depth_stencil_attachment || usage.input_attachment || - usage.transient_attachment + if usage.color_attachment || usage.depth_stencil_attachment || + usage.input_attachment || usage.transient_attachment { match format.ty() { FormatTy::Float | FormatTy::Compressed | FormatTy::Uint | FormatTy::Sint => { - supported_samples &= device.physical_device().limits() - .framebuffer_color_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .framebuffer_color_sample_counts(); }, FormatTy::Depth => { - supported_samples &= device.physical_device().limits() - .framebuffer_depth_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .framebuffer_depth_sample_counts(); }, FormatTy::Stencil => { - supported_samples &= device.physical_device().limits() - .framebuffer_stencil_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .framebuffer_stencil_sample_counts(); }, FormatTy::DepthStencil => { - supported_samples &= device.physical_device().limits() - .framebuffer_depth_sample_counts(); - supported_samples &= device.physical_device().limits() - .framebuffer_stencil_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .framebuffer_depth_sample_counts(); + supported_samples &= device + .physical_device() + .limits() + .framebuffer_stencil_sample_counts(); }, } } @@ -295,30 +342,65 @@ impl UnsafeImage { // Decoding the dimensions. let (ty, extent, array_layers, flags) = match dimensions { - ImageDimensions::Dim1d { width, array_layers } => { + ImageDimensions::Dim1d { + width, + array_layers, + } => { if width == 0 || array_layers == 0 { - return Err(ImageCreationError::UnsupportedDimensions { dimensions: dimensions }); + return Err(ImageCreationError::UnsupportedDimensions { + dimensions: dimensions, + }); } - let extent = vk::Extent3D { width: width, height: 1, depth: 1 }; + let extent = vk::Extent3D { + width: width, + height: 1, + depth: 1, + }; (vk::IMAGE_TYPE_1D, extent, array_layers, 0) }, - ImageDimensions::Dim2d { width, height, array_layers, cubemap_compatible } => { + ImageDimensions::Dim2d { + width, + height, + array_layers, + cubemap_compatible, + } => { if width == 0 || height == 0 || array_layers == 0 { - return Err(ImageCreationError::UnsupportedDimensions { dimensions: dimensions }); + return Err(ImageCreationError::UnsupportedDimensions { + dimensions: dimensions, + }); } if cubemap_compatible && width != height { - return Err(ImageCreationError::UnsupportedDimensions { dimensions: dimensions }); + return Err(ImageCreationError::UnsupportedDimensions { + dimensions: dimensions, + }); } - let extent = vk::Extent3D { width: width, height: height, depth: 1 }; - let flags = if cubemap_compatible { vk::IMAGE_CREATE_CUBE_COMPATIBLE_BIT } - else { 0 }; + let extent = vk::Extent3D { + width: width, + height: height, + depth: 1, + }; + let flags = if cubemap_compatible { + vk::IMAGE_CREATE_CUBE_COMPATIBLE_BIT + } else { + 0 + }; (vk::IMAGE_TYPE_2D, extent, array_layers, flags) }, - ImageDimensions::Dim3d { width, height, depth } => { + ImageDimensions::Dim3d { + width, + height, + depth, + } => { if width == 0 || height == 0 || depth == 0 { - return Err(ImageCreationError::UnsupportedDimensions { dimensions: dimensions }); + return Err(ImageCreationError::UnsupportedDimensions { + dimensions: dimensions, + }); } - let extent = vk::Extent3D { width: width, height: height, depth: depth }; + let extent = vk::Extent3D { + width: width, + height: height, + depth: depth, + }; (vk::IMAGE_TYPE_3D, extent, 1, 0) }, }; @@ -344,9 +426,10 @@ impl UnsafeImage { if (flags & vk::IMAGE_CREATE_CUBE_COMPATIBLE_BIT) != 0 { let limit = device.physical_device().limits().max_image_dimension_cube(); - debug_assert_eq!(extent.width, extent.height); // checked above + debug_assert_eq!(extent.width, extent.height); // checked above if extent.width > limit { - let err = ImageCreationError::UnsupportedDimensions { dimensions: dimensions }; + let err = + ImageCreationError::UnsupportedDimensions { dimensions: dimensions }; capabilities_error = Some(err); } } @@ -358,7 +441,7 @@ impl UnsafeImage { capabilities_error = Some(err); } }, - _ => unreachable!() + _ => unreachable!(), }; let usage = usage.to_usage_bits(); @@ -374,19 +457,26 @@ impl UnsafeImage { let mut output = mem::uninitialized(); let physical_device = device.physical_device().internal_object(); - let r = vk_i.GetPhysicalDeviceImageFormatProperties(physical_device, format as u32, ty, - tiling, usage, 0 /* TODO */, + let r = vk_i.GetPhysicalDeviceImageFormatProperties(physical_device, + format as u32, + ty, + tiling, + usage, + 0, /* TODO */ &mut output); match check_errors(r) { Ok(_) => (), - Err(Error::FormatNotSupported) => return Err(ImageCreationError::FormatNotSupported), + Err(Error::FormatNotSupported) => + return Err(ImageCreationError::FormatNotSupported), Err(err) => return Err(err.into()), } if extent.width > output.maxExtent.width || extent.height > output.maxExtent.height || - extent.depth > output.maxExtent.depth || mipmaps > output.maxMipLevels || - array_layers > output.maxArrayLayers || (num_samples & output.sampleCounts) == 0 + extent.depth > output.maxExtent.depth || + mipmaps > output.maxMipLevels || + array_layers > output.maxArrayLayers || + (num_samples & output.sampleCounts) == 0 { return Err(capabilities_error); } @@ -421,8 +511,10 @@ impl UnsafeImage { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateImage(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateImage(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; @@ -453,8 +545,7 @@ impl UnsafeImage { /// This function is for example used at the swapchain's initialization. pub unsafe fn from_raw(device: Arc, handle: u64, usage: u32, format: Format, dimensions: ImageDimensions, samples: u32, mipmaps: u32) - -> UnsafeImage - { + -> UnsafeImage { let vk_i = device.instance().pointers(); let physical_device = device.physical_device().internal_object(); @@ -472,27 +563,28 @@ impl UnsafeImage { samples: samples, mipmaps: mipmaps, format_features: output.optimalTilingFeatures, - needs_destruction: false, // TODO: pass as parameter + needs_destruction: false, // TODO: pass as parameter } } - pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize) - -> Result<(), OomError> - { + pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize) -> Result<(), OomError> { let vk = self.device.pointers(); // We check for correctness in debug mode. debug_assert!({ - let mut mem_reqs = mem::uninitialized(); - vk.GetImageMemoryRequirements(self.device.internal_object(), self.image, - &mut mem_reqs); - mem_reqs.size <= (memory.size() - offset) as u64 && - (offset as u64 % mem_reqs.alignment) == 0 && - mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0 - }); + let mut mem_reqs = mem::uninitialized(); + vk.GetImageMemoryRequirements(self.device.internal_object(), + self.image, + &mut mem_reqs); + mem_reqs.size <= (memory.size() - offset) as u64 && + (offset as u64 % mem_reqs.alignment) == 0 && + mem_reqs.memoryTypeBits & (1 << memory.memory_type().id()) != 0 + }); - try!(check_errors(vk.BindImageMemory(self.device.internal_object(), self.image, - memory.internal_object(), offset as vk::DeviceSize))); + check_errors(vk.BindImageMemory(self.device.internal_object(), + self.image, + memory.internal_object(), + offset as vk::DeviceSize))?; Ok(()) } @@ -599,7 +691,9 @@ impl UnsafeImage { }; let mut out = mem::uninitialized(); - vk.GetImageSubresourceLayout(self.device.internal_object(), self.image, &subresource, + vk.GetImageSubresourceLayout(self.device.internal_object(), + self.image, + &subresource, &mut out); LinearLayout { @@ -706,7 +800,10 @@ pub enum ImageCreationError { /// Not enough memory. OomError(OomError), /// A wrong number of mipmaps was provided. - InvalidMipmapsCount { obtained: u32, valid_range: Range }, + InvalidMipmapsCount { + obtained: u32, + valid_range: Range, + }, /// The requeted number of samples is not supported, or is 0. UnsupportedSamplesCount { obtained: u32 }, /// The dimensions are too large, or one of the dimensions is 0. @@ -724,16 +821,17 @@ impl error::Error for ImageCreationError { fn description(&self) -> &str { match *self { ImageCreationError::OomError(_) => "not enough memory available", - ImageCreationError::InvalidMipmapsCount { .. } => "a wrong number of mipmaps was \ - provided", - ImageCreationError::UnsupportedSamplesCount { .. } => "the requeted number of samples \ - is not supported, or is 0", - ImageCreationError::UnsupportedDimensions { .. } => "the dimensions are too large, or \ - one of the dimensions is 0", - ImageCreationError::FormatNotSupported => "the requested format is not supported by \ - the Vulkan implementation", - ImageCreationError::UnsupportedUsage => "the format is supported, but at least one \ - of the requested usages is not supported", + ImageCreationError::InvalidMipmapsCount { .. } => + "a wrong number of mipmaps was provided", + ImageCreationError::UnsupportedSamplesCount { .. } => + "the requeted number of samples is not supported, or is 0", + ImageCreationError::UnsupportedDimensions { .. } => + "the dimensions are too large, or one of the dimensions is 0", + ImageCreationError::FormatNotSupported => + "the requested format is not supported by the Vulkan implementation", + ImageCreationError::UnsupportedUsage => + "the format is supported, but at least one of the requested usages is not \ + supported", ImageCreationError::ShaderStorageImageMultisampleFeatureNotEnabled => { "the `shader_storage_image_multisample` feature must be enabled to create such \ an image" @@ -745,7 +843,7 @@ impl error::Error for ImageCreationError { fn cause(&self) -> Option<&error::Error> { match *self { ImageCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -770,7 +868,7 @@ impl From for ImageCreationError { match err { err @ Error::OutOfHostMemory => ImageCreationError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => ImageCreationError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -810,8 +908,8 @@ pub struct UnsafeImageView { impl UnsafeImageView { /// See the docs of new(). pub unsafe fn raw(image: &UnsafeImage, ty: ViewType, mipmap_levels: Range, - array_layers: Range) -> Result - { + array_layers: Range) + -> Result { let vk = image.device.pointers(); assert!(mipmap_levels.end > mipmap_levels.start); @@ -830,30 +928,39 @@ impl UnsafeImageView { let view_type = match (image.dimensions(), ty, array_layers.end - array_layers.start) { (ImageDimensions::Dim1d { .. }, ViewType::Dim1d, 1) => vk::IMAGE_VIEW_TYPE_1D, - (ImageDimensions::Dim1d { .. }, ViewType::Dim1dArray, _) => vk::IMAGE_VIEW_TYPE_1D_ARRAY, + (ImageDimensions::Dim1d { .. }, ViewType::Dim1dArray, _) => + vk::IMAGE_VIEW_TYPE_1D_ARRAY, (ImageDimensions::Dim2d { .. }, ViewType::Dim2d, 1) => vk::IMAGE_VIEW_TYPE_2D, - (ImageDimensions::Dim2d { .. }, ViewType::Dim2dArray, _) => vk::IMAGE_VIEW_TYPE_2D_ARRAY, - (ImageDimensions::Dim2d { cubemap_compatible, .. }, ViewType::Cubemap, n) if cubemap_compatible => { + (ImageDimensions::Dim2d { .. }, ViewType::Dim2dArray, _) => + vk::IMAGE_VIEW_TYPE_2D_ARRAY, + (ImageDimensions::Dim2d { cubemap_compatible, .. }, ViewType::Cubemap, n) + if cubemap_compatible => { assert_eq!(n, 6); vk::IMAGE_VIEW_TYPE_CUBE }, - (ImageDimensions::Dim2d { cubemap_compatible, .. }, ViewType::CubemapArray, n) if cubemap_compatible => { + (ImageDimensions::Dim2d { cubemap_compatible, .. }, ViewType::CubemapArray, n) + if cubemap_compatible => { assert_eq!(n % 6, 0); vk::IMAGE_VIEW_TYPE_CUBE_ARRAY }, (ImageDimensions::Dim3d { .. }, ViewType::Dim3d, _) => vk::IMAGE_VIEW_TYPE_3D, - _ => panic!() + _ => panic!(), }; let view = { let infos = vk::ImageViewCreateInfo { sType: vk::STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved image: image.internal_object(), viewType: view_type, format: image.format as u32, - components: vk::ComponentMapping { r: 0, g: 0, b: 0, a: 0 }, // FIXME: + components: vk::ComponentMapping { + r: 0, + g: 0, + b: 0, + a: 0, + }, // FIXME: subresourceRange: vk::ImageSubresourceRange { aspectMask: aspect_mask, baseMipLevel: mipmap_levels.start, @@ -864,18 +971,20 @@ impl UnsafeImageView { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateImageView(image.device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateImageView(image.device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(UnsafeImageView { - view: view, - device: image.device.clone(), - usage: image.usage, - identity_swizzle: true, // FIXME: - format: image.format, - }) + view: view, + device: image.device.clone(), + usage: image.usage, + identity_swizzle: true, // FIXME: + format: image.format, + }) } /// Creates a new view from an image. @@ -895,8 +1004,8 @@ impl UnsafeImageView { /// #[inline] pub unsafe fn new(image: &UnsafeImage, ty: ViewType, mipmap_levels: Range, - array_layers: Range) -> UnsafeImageView - { + array_layers: Range) + -> UnsafeImageView { UnsafeImageView::raw(image, ty, mipmap_levels, array_layers).unwrap() } @@ -978,11 +1087,11 @@ mod tests { use std::u32; use super::ImageCreationError; - use super::UnsafeImage; use super::ImageUsage; + use super::UnsafeImage; - use image::ImageDimensions; use format::Format; + use image::ImageDimensions; use sync::Sharing; #[test] @@ -991,14 +1100,24 @@ mod tests { let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let (_img, _) = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + 1, + Sharing::Exclusive::>, + false, + false) }.unwrap(); } @@ -1009,14 +1128,24 @@ mod tests { let usage = ImageUsage { transient_attachment: true, color_attachment: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let (_img, _) = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + 1, + Sharing::Exclusive::>, + false, + false) }.unwrap(); } @@ -1026,19 +1155,29 @@ mod tests { let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 0, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 0, + 1, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::UnsupportedSamplesCount { .. }) => (), - _ => panic!() + _ => panic!(), }; } @@ -1048,19 +1187,29 @@ mod tests { let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 5, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 5, + 1, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::UnsupportedSamplesCount { .. }) => (), - _ => panic!() + _ => panic!(), }; } @@ -1070,45 +1219,68 @@ mod tests { let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, 0, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + 0, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::InvalidMipmapsCount { .. }) => (), - _ => panic!() + _ => panic!(), }; } #[test] - #[ignore] // TODO: AMD card seems to support a u32::MAX number of mipmaps + #[ignore] // TODO: AMD card seems to support a u32::MAX number of mipmaps fn mipmaps_too_high() { let (device, _) = gfx_dev_and_queue!(); let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, u32::MAX, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + u32::MAX, + Sharing::Exclusive::>, + false, + false) }; match res { - Err(ImageCreationError::InvalidMipmapsCount { obtained, valid_range }) => { + Err(ImageCreationError::InvalidMipmapsCount { + obtained, + valid_range, + }) => { assert_eq!(obtained, u32::MAX); assert_eq!(valid_range.start, 1); }, - _ => panic!() + _ => panic!(), }; } @@ -1118,20 +1290,30 @@ mod tests { let usage = ImageUsage { storage: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 2, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 2, + 1, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::ShaderStorageImageMultisampleFeatureNotEnabled) => (), Err(ImageCreationError::UnsupportedSamplesCount { .. }) => (), // unlikely but possible - _ => panic!() + _ => panic!(), }; } @@ -1141,20 +1323,30 @@ mod tests { let usage = ImageUsage { color_attachment: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::ASTC_5x4UnormBlock, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, u32::MAX, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::ASTC_5x4UnormBlock, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + u32::MAX, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::FormatNotSupported) => (), Err(ImageCreationError::UnsupportedUsage) => (), - _ => panic!() + _ => panic!(), }; } @@ -1165,19 +1357,29 @@ mod tests { let usage = ImageUsage { transient_attachment: true, sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 32, array_layers: 1, - cubemap_compatible: false }, 1, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 32, + array_layers: 1, + cubemap_compatible: false, + }, + 1, + 1, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::UnsupportedUsage) => (), - _ => panic!() + _ => panic!(), }; } @@ -1187,19 +1389,29 @@ mod tests { let usage = ImageUsage { sampled: true, - .. ImageUsage::none() + ..ImageUsage::none() }; let res = unsafe { - UnsafeImage::new(device, usage, Format::R8G8B8A8Unorm, - ImageDimensions::Dim2d { width: 32, height: 64, array_layers: 1, - cubemap_compatible: true }, 1, 1, - Sharing::Exclusive::>, false, false) + UnsafeImage::new(device, + usage, + Format::R8G8B8A8Unorm, + ImageDimensions::Dim2d { + width: 32, + height: 64, + array_layers: 1, + cubemap_compatible: true, + }, + 1, + 1, + Sharing::Exclusive::>, + false, + false) }; match res { Err(ImageCreationError::UnsupportedDimensions { .. }) => (), - _ => panic!() + _ => panic!(), }; } } diff --git a/vulkano/src/image/traits.rs b/vulkano/src/image/traits.rs index 54f5d37c..cba0609f 100644 --- a/vulkano/src/image/traits.rs +++ b/vulkano/src/image/traits.rs @@ -11,12 +11,12 @@ use buffer::BufferAccess; use device::Queue; use format::ClearValue; use format::Format; -use format::PossibleFloatFormatDesc; -use format::PossibleUintFormatDesc; -use format::PossibleSintFormatDesc; use format::PossibleDepthFormatDesc; -use format::PossibleStencilFormatDesc; use format::PossibleDepthStencilFormatDesc; +use format::PossibleFloatFormatDesc; +use format::PossibleSintFormatDesc; +use format::PossibleStencilFormatDesc; +use format::PossibleUintFormatDesc; use image::Dimensions; use image::ImageDimensions; use image::ImageLayout; @@ -47,7 +47,7 @@ pub unsafe trait ImageAccess { } /// Returns true if the image has a depth component. In other words, if it is a depth or a - /// depth-stencil format. + /// depth-stencil format. #[inline] fn has_depth(&self) -> bool { let format = self.format(); @@ -55,7 +55,7 @@ pub unsafe trait ImageAccess { } /// Returns true if the image has a stencil component. In other words, if it is a stencil or a - /// depth-stencil format. + /// depth-stencil format. #[inline] fn has_stencil(&self) -> bool { let format = self.format(); @@ -117,10 +117,10 @@ pub unsafe trait ImageAccess { /// /// If this function returns `false`, this means that we are allowed to access the offset/size /// of `self` at the same time as the offset/size of `other` without causing a data race. - fn conflicts_buffer(&self, self_first_layer: u32, self_num_layers: u32, self_first_mipmap: u32, - self_num_mipmaps: u32, other: &BufferAccess, other_offset: usize, - other_size: usize) -> bool - { + fn conflicts_buffer(&self, self_first_layer: u32, self_num_layers: u32, + self_first_mipmap: u32, self_num_mipmaps: u32, other: &BufferAccess, + other_offset: usize, other_size: usize) + -> bool { // TODO: should we really provide a default implementation? false } @@ -132,11 +132,11 @@ pub unsafe trait ImageAccess { /// /// If this function returns `false`, this means that we are allowed to access the offset/size /// of `self` at the same time as the offset/size of `other` without causing a data race. - fn conflicts_image(&self, self_first_layer: u32, self_num_layers: u32, self_first_mipmap: u32, - self_num_mipmaps: u32, other: &ImageAccess, + fn conflicts_image(&self, self_first_layer: u32, self_num_layers: u32, + self_first_mipmap: u32, self_num_mipmaps: u32, other: &ImageAccess, other_first_layer: u32, other_num_layers: u32, other_first_mipmap: u32, - other_num_mipmaps: u32) -> bool - { + other_num_mipmaps: u32) + -> bool { // TODO: should we really provide a default implementation? // TODO: debug asserts to check for ranges @@ -166,15 +166,27 @@ pub unsafe trait ImageAccess { /// Shortcut for `conflicts_buffer` that compares the whole buffer to another. #[inline] fn conflicts_buffer_all(&self, other: &BufferAccess) -> bool { - self.conflicts_buffer(0, self.dimensions().array_layers(), 0, self.mipmap_levels(), - other, 0, other.size()) + self.conflicts_buffer(0, + self.dimensions().array_layers(), + 0, + self.mipmap_levels(), + other, + 0, + other.size()) } /// Shortcut for `conflicts_image` that compares the whole buffer to a whole image. #[inline] fn conflicts_image_all(&self, other: &ImageAccess) -> bool { - self.conflicts_image(0, self.dimensions().array_layers(), 0, self.mipmap_levels(), - other, 0, other.dimensions().array_layers(), 0, other.mipmap_levels()) + self.conflicts_image(0, + self.dimensions().array_layers(), + 0, + self.mipmap_levels(), + other, + 0, + other.dimensions().array_layers(), + 0, + other.mipmap_levels()) } /// Shortcut for `conflict_key` that grabs the key of the whole buffer. @@ -215,7 +227,10 @@ pub unsafe trait ImageAccess { unsafe fn unlock(&self); } -unsafe impl ImageAccess for T where T: SafeDeref, T::Target: ImageAccess { +unsafe impl ImageAccess for T + where T: SafeDeref, + T::Target: ImageAccess +{ #[inline] fn inner(&self) -> &UnsafeImage { (**self).inner() @@ -233,8 +248,7 @@ unsafe impl ImageAccess for T where T: SafeDeref, T::Target: ImageAccess { #[inline] fn conflict_key(&self, first_layer: u32, num_layers: u32, first_mipmap: u32, num_mipmaps: u32) - -> u64 - { + -> u64 { (**self).conflict_key(first_layer, num_layers, first_mipmap, num_mipmaps) } @@ -286,9 +300,9 @@ unsafe impl ImageAccess for ImageAccessFromUndefinedLayout #[inline] fn conflict_key(&self, first_layer: u32, num_layers: u32, first_mipmap: u32, num_mipmaps: u32) - -> u64 - { - self.image.conflict_key(first_layer, num_layers, first_mipmap, num_mipmaps) + -> u64 { + self.image + .conflict_key(first_layer, num_layers, first_mipmap, num_mipmaps) } #[inline] @@ -360,12 +374,17 @@ pub unsafe trait ImageViewAccess { /// This method should check whether the sampler's configuration can be used with the format /// of the view. // TODO: return a Result - fn can_be_sampled(&self, sampler: &Sampler) -> bool { true /* FIXME */ } + fn can_be_sampled(&self, sampler: &Sampler) -> bool { + true /* FIXME */ + } //fn usable_as_render_pass_attachment(&self, ???) -> Result<(), ???>; } -unsafe impl ImageViewAccess for T where T: SafeDeref, T::Target: ImageViewAccess { +unsafe impl ImageViewAccess for T + where T: SafeDeref, + T::Target: ImageViewAccess +{ #[inline] fn parent(&self) -> &ImageAccess { (**self).parent() diff --git a/vulkano/src/image/usage.rs b/vulkano/src/image/usage.rs index 7c9a5aa9..8dc73023 100644 --- a/vulkano/src/image/usage.rs +++ b/vulkano/src/image/usage.rs @@ -98,14 +98,30 @@ impl ImageUsage { #[inline] pub fn to_usage_bits(&self) -> vk::ImageUsageFlagBits { let mut result = 0; - if self.transfer_source { result |= vk::IMAGE_USAGE_TRANSFER_SRC_BIT; } - if self.transfer_dest { result |= vk::IMAGE_USAGE_TRANSFER_DST_BIT; } - if self.sampled { result |= vk::IMAGE_USAGE_SAMPLED_BIT; } - if self.storage { result |= vk::IMAGE_USAGE_STORAGE_BIT; } - if self.color_attachment { result |= vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } - if self.depth_stencil_attachment { result |= vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; } - if self.transient_attachment { result |= vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; } - if self.input_attachment { result |= vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } + if self.transfer_source { + result |= vk::IMAGE_USAGE_TRANSFER_SRC_BIT; + } + if self.transfer_dest { + result |= vk::IMAGE_USAGE_TRANSFER_DST_BIT; + } + if self.sampled { + result |= vk::IMAGE_USAGE_SAMPLED_BIT; + } + if self.storage { + result |= vk::IMAGE_USAGE_STORAGE_BIT; + } + if self.color_attachment { + result |= vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + if self.depth_stencil_attachment { + result |= vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } + if self.transient_attachment { + result |= vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; + } + if self.input_attachment { + result |= vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + } result } diff --git a/vulkano/src/instance/debug.rs b/vulkano/src/instance/debug.rs index 96801281..4023b110 100644 --- a/vulkano/src/instance/debug.rs +++ b/vulkano/src/instance/debug.rs @@ -24,7 +24,7 @@ //! # use std::sync::Arc; //! # let instance: Arc = return; //! use vulkano::instance::debug::DebugCallback; -//! +//! //! let _callback = DebugCallback::errors_and_warnings(&instance, |msg| { //! println!("Debug callback: {:?}", msg.description); //! }).ok(); @@ -34,23 +34,23 @@ //! //! Note that you must keep the `_callback` object alive for as long as you want your callback to //! be callable. If you don't store the return value of `DebugCallback`'s constructor in a -//! variable, it will be immediately destroyed and your callback will not work. +//! variable, it will be immediately destroyed and your callback will not work. //! use std::error; use std::ffi::CStr; use std::fmt; use std::mem; -use std::os::raw::{c_void, c_char}; +use std::os::raw::{c_char, c_void}; use std::panic; use std::ptr; use std::sync::Arc; use instance::Instance; -use check_errors; use Error; use VulkanObject; +use check_errors; use vk; /// Registration of a callback called by validation layers. @@ -80,27 +80,27 @@ impl DebugCallback { // that can't be casted to a `*const c_void`. let user_callback = Box::new(Box::new(user_callback) as Box<_>); - extern "system" fn callback(ty: vk::DebugReportFlagsEXT, - _: vk::DebugReportObjectTypeEXT, _: u64, _: usize, - _: i32, layer_prefix: *const c_char, - description: *const c_char, user_data: *mut c_void) -> u32 - { + extern "system" fn callback(ty: vk::DebugReportFlagsEXT, _: vk::DebugReportObjectTypeEXT, + _: u64, _: usize, _: i32, layer_prefix: *const c_char, + description: *const c_char, user_data: *mut c_void) + -> u32 { unsafe { let user_callback = user_data as *mut Box as *const _; let user_callback: &Box = &*user_callback; - let layer_prefix = CStr::from_ptr(layer_prefix).to_str() - .expect("debug callback message \ - not utf-8"); - let description = CStr::from_ptr(description).to_str() - .expect("debug callback message \ - not utf-8"); + let layer_prefix = CStr::from_ptr(layer_prefix) + .to_str() + .expect("debug callback message not utf-8"); + let description = CStr::from_ptr(description) + .to_str() + .expect("debug callback message not utf-8"); let message = Message { ty: MessageTypes { information: (ty & vk::DEBUG_REPORT_INFORMATION_BIT_EXT) != 0, warning: (ty & vk::DEBUG_REPORT_WARNING_BIT_EXT) != 0, - performance_warning: (ty & vk::DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0, + performance_warning: (ty & vk::DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != + 0, error: (ty & vk::DEBUG_REPORT_ERROR_BIT_EXT) != 0, debug: (ty & vk::DEBUG_REPORT_DEBUG_BIT_EXT) != 0, }, @@ -111,8 +111,8 @@ impl DebugCallback { // Since we box the closure, the type system doesn't detect that the `UnwindSafe` // bound is enforced. Therefore we enforce it manually. let _ = panic::catch_unwind(panic::AssertUnwindSafe(move || { - user_callback(&message); - })); + user_callback(&message); + })); vk::FALSE } @@ -120,11 +120,21 @@ impl DebugCallback { let flags = { let mut flags = 0; - if messages.information { flags |= vk::DEBUG_REPORT_INFORMATION_BIT_EXT; } - if messages.warning { flags |= vk::DEBUG_REPORT_WARNING_BIT_EXT; } - if messages.performance_warning { flags |= vk::DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; } - if messages.error { flags |= vk::DEBUG_REPORT_ERROR_BIT_EXT; } - if messages.debug { flags |= vk::DEBUG_REPORT_DEBUG_BIT_EXT; } + if messages.information { + flags |= vk::DEBUG_REPORT_INFORMATION_BIT_EXT; + } + if messages.warning { + flags |= vk::DEBUG_REPORT_WARNING_BIT_EXT; + } + if messages.performance_warning { + flags |= vk::DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + } + if messages.error { + flags |= vk::DEBUG_REPORT_ERROR_BIT_EXT; + } + if messages.debug { + flags |= vk::DEBUG_REPORT_DEBUG_BIT_EXT; + } flags }; @@ -140,16 +150,18 @@ impl DebugCallback { let debug_report_callback = unsafe { let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateDebugReportCallbackEXT(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateDebugReportCallbackEXT(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(DebugCallback { - instance: instance.clone(), - debug_report_callback: debug_report_callback, - user_callback: user_callback, - }) + instance: instance.clone(), + debug_report_callback: debug_report_callback, + user_callback: user_callback, + }) } /// Initializes a debug callback with errors and warnings. @@ -170,7 +182,8 @@ impl Drop for DebugCallback { unsafe { let vk = self.instance.pointers(); vk.DestroyDebugReportCallbackEXT(self.instance.internal_object(), - self.debug_report_callback, ptr::null()); + self.debug_report_callback, + ptr::null()); } } } @@ -206,7 +219,7 @@ impl MessageTypes { pub fn errors() -> MessageTypes { MessageTypes { error: true, - .. MessageTypes::none() + ..MessageTypes::none() } } @@ -218,7 +231,7 @@ impl MessageTypes { error: true, warning: true, performance_warning: true, - .. MessageTypes::none() + ..MessageTypes::none() } } @@ -246,8 +259,8 @@ impl error::Error for DebugCallbackCreationError { #[inline] fn description(&self) -> &str { match *self { - DebugCallbackCreationError::MissingExtension => "the `EXT_debug_report` extension was \ - not enabled", + DebugCallbackCreationError::MissingExtension => + "the `EXT_debug_report` extension was not enabled", } } } diff --git a/vulkano/src/instance/extensions.rs b/vulkano/src/instance/extensions.rs index 7e9ee6b2..73e52225 100644 --- a/vulkano/src/instance/extensions.rs +++ b/vulkano/src/instance/extensions.rs @@ -7,21 +7,21 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use std::collections::HashSet; use std::error; -use std::ffi::{CString, CStr}; +use std::ffi::{CStr, CString}; use std::fmt; use std::ptr; use std::str; -use std::collections::HashSet; use Error; use OomError; use VulkanObject; +use check_errors; use instance::PhysicalDevice; use instance::loader; use instance::loader::LoadingError; use vk; -use check_errors; macro_rules! extensions { ($sname:ident, $rawname:ident, $($ext:ident => $s:expr,)*) => ( @@ -402,7 +402,7 @@ impl From for SupportedExtensionsError { err @ Error::OutOfDeviceMemory => { SupportedExtensionsError::OomError(OomError::from(err)) }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -415,8 +415,8 @@ pub struct Unbuildable(()); #[cfg(test)] mod tests { - use instance::{InstanceExtensions, RawInstanceExtensions}; use instance::{DeviceExtensions, RawDeviceExtensions}; + use instance::{InstanceExtensions, RawInstanceExtensions}; #[test] fn empty_extensions() { diff --git a/vulkano/src/instance/instance.rs b/vulkano/src/instance/instance.rs index 2212f510..8077796a 100644 --- a/vulkano/src/instance/instance.rs +++ b/vulkano/src/instance/instance.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::borrow::Cow; use std::error; use std::ffi::CStr; @@ -16,19 +17,18 @@ use std::mem; use std::ptr; use std::slice; use std::sync::Arc; -use smallvec::SmallVec; -use instance::loader; -use instance::loader::LoadingError; -use check_errors; use Error; use OomError; use VulkanObject; +use check_errors; +use instance::loader; +use instance::loader::LoadingError; use vk; use features::Features; -use version::Version; use instance::{InstanceExtensions, RawInstanceExtensions}; +use version::Version; /// An instance of a Vulkan context. This is the main object that should be created by an /// application before everything else. @@ -114,36 +114,41 @@ impl Instance { // TODO: add a test for these ^ // TODO: if no allocator is specified by the user, use Rust's allocator instead of leaving // the choice to Vulkan - pub fn new<'a, L, Ext>(app_infos: Option<&ApplicationInfo>, extensions: Ext, - layers: L) -> Result, InstanceCreationError> + pub fn new<'a, L, Ext>(app_infos: Option<&ApplicationInfo>, extensions: Ext, layers: L) + -> Result, InstanceCreationError> where L: IntoIterator, - Ext: Into, + Ext: Into { - let layers = layers.into_iter().map(|&layer| { - CString::new(layer).unwrap() - }).collect::>(); + let layers = layers + .into_iter() + .map(|&layer| CString::new(layer).unwrap()) + .collect::>(); Instance::new_inner(app_infos, extensions.into(), layers) } fn new_inner(app_infos: Option<&ApplicationInfo>, extensions: RawInstanceExtensions, - layers: SmallVec<[CString; 16]>) -> Result, InstanceCreationError> - { + layers: SmallVec<[CString; 16]>) + -> Result, InstanceCreationError> { // TODO: For now there are still buggy drivers that will segfault if you don't pass any // appinfos. Therefore for now we ensure that it can't be `None`. let def = Default::default(); let app_infos = match app_infos { Some(a) => Some(a), - None => Some(&def) + None => Some(&def), }; // Building the CStrings from the `str`s within `app_infos`. // They need to be created ahead of time, since we pass pointers to them. let app_infos_strings = if let Some(app_infos) = app_infos { - Some(( - app_infos.application_name.clone().map(|n| CString::new(n.as_bytes().to_owned()).unwrap()), - app_infos.engine_name.clone().map(|n| CString::new(n.as_bytes().to_owned()).unwrap()) - )) + Some((app_infos + .application_name + .clone() + .map(|n| CString::new(n.as_bytes().to_owned()).unwrap()), + app_infos + .engine_name + .clone() + .map(|n| CString::new(n.as_bytes().to_owned()).unwrap()))) } else { None }; @@ -153,11 +158,33 @@ impl Instance { Some(vk::ApplicationInfo { sType: vk::STRUCTURE_TYPE_APPLICATION_INFO, pNext: ptr::null(), - pApplicationName: app_infos_strings.as_ref().unwrap().0.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), - applicationVersion: app_infos.application_version.map(|v| v.into_vulkan_version()).unwrap_or(0), - pEngineName: app_infos_strings.as_ref().unwrap().1.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), - engineVersion: app_infos.engine_version.map(|v| v.into_vulkan_version()).unwrap_or(0), - apiVersion: Version { major: 1, minor: 0, patch: 0 }.into_vulkan_version(), // TODO: + pApplicationName: app_infos_strings + .as_ref() + .unwrap() + .0 + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()), + applicationVersion: app_infos + .application_version + .map(|v| v.into_vulkan_version()) + .unwrap_or(0), + pEngineName: app_infos_strings + .as_ref() + .unwrap() + .1 + .as_ref() + .map(|s| s.as_ptr()) + .unwrap_or(ptr::null()), + engineVersion: app_infos + .engine_version + .map(|v| v.into_vulkan_version()) + .unwrap_or(0), + apiVersion: Version { + major: 1, + minor: 0, + patch: 0, + }.into_vulkan_version(), // TODO: }) } else { @@ -165,15 +192,17 @@ impl Instance { }; // FIXME: check whether each layer is supported - let layers_ptr = layers.iter().map(|layer| { - layer.as_ptr() - }).collect::>(); + let layers_ptr = layers + .iter() + .map(|layer| layer.as_ptr()) + .collect::>(); - let extensions_list = extensions.iter().map(|extension| { - extension.as_ptr() - }).collect::>(); + let extensions_list = extensions + .iter() + .map(|extension| extension.as_ptr()) + .collect::>(); - let entry_points = try!(loader::entry_points()); + let entry_points = loader::entry_points()?; // Creating the Vulkan instance. let instance = unsafe { @@ -193,26 +222,26 @@ impl Instance { ppEnabledExtensionNames: extensions_list.as_ptr(), }; - try!(check_errors(entry_points.CreateInstance(&infos, ptr::null(), &mut output))); + check_errors(entry_points.CreateInstance(&infos, ptr::null(), &mut output))?; output }; // Loading the function pointers of the newly-created instance. let vk = { - let f = loader::static_functions().unwrap(); // TODO: return proper error + let f = loader::static_functions().unwrap(); // TODO: return proper error vk::InstancePointers::load(|name| unsafe { - mem::transmute(f.GetInstanceProcAddr(instance, name.as_ptr())) - }) + mem::transmute(f.GetInstanceProcAddr(instance, + name.as_ptr())) + }) }; // Enumerating all physical devices. let physical_devices: Vec = unsafe { let mut num = 0; - try!(check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, ptr::null_mut()))); + check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, ptr::null_mut()))?; let mut devices = Vec::with_capacity(num as usize); - try!(check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, - devices.as_mut_ptr()))); + check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, devices.as_mut_ptr()))?; devices.set_len(num as usize); devices }; @@ -229,13 +258,13 @@ impl Instance { }; Ok(Arc::new(Instance { - instance: instance, - //alloc: None, - physical_devices: physical_devices, - vk: vk, - extensions: extensions, - layers: layers, - })) + instance: instance, + //alloc: None, + physical_devices: physical_devices, + vk: vk, + extensions: extensions, + layers: layers, + })) } /// Initialize all physical devices @@ -255,8 +284,7 @@ impl Instance { vk.GetPhysicalDeviceQueueFamilyProperties(device, &mut num, ptr::null_mut()); let mut families = Vec::with_capacity(num as usize); - vk.GetPhysicalDeviceQueueFamilyProperties(device, &mut num, - families.as_mut_ptr()); + vk.GetPhysicalDeviceQueueFamilyProperties(device, &mut num, families.as_mut_ptr()); families.set_len(num as usize); families }; @@ -274,20 +302,22 @@ impl Instance { }; output.push(PhysicalDeviceInfos { - device: device, - properties: properties, - memory: memory, - queue_families: queue_families, - available_features: Features::from(available_features), - }); + device: device, + properties: properties, + memory: memory, + queue_families: queue_families, + available_features: Features::from(available_features), + }); } output } /// Initialize all physical devices, but use VK_KHR_get_physical_device_properties2 /// TODO: Query extension-specific physical device properties, once a new instance extension is supported. - fn init_physical_devices2(vk: &vk::InstancePointers, physical_devices: Vec, - extensions: &InstanceExtensions) -> Vec { + fn init_physical_devices2(vk: &vk::InstancePointers, + physical_devices: Vec, + extensions: &InstanceExtensions) + -> Vec { let mut output = Vec::with_capacity(physical_devices.len()); for device in physical_devices.into_iter() { @@ -306,17 +336,23 @@ impl Instance { let mut num = 0; vk.GetPhysicalDeviceQueueFamilyProperties2KHR(device, &mut num, ptr::null_mut()); - let mut families = (0 .. num).map(|_| { - vk::QueueFamilyProperties2KHR { - sType: vk::STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR, - pNext: ptr::null_mut(), - queueFamilyProperties: mem::uninitialized(), - } - }).collect::>(); + let mut families = (0 .. num) + .map(|_| { + vk::QueueFamilyProperties2KHR { + sType: vk::STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR, + pNext: ptr::null_mut(), + queueFamilyProperties: mem::uninitialized(), + } + }) + .collect::>(); - vk.GetPhysicalDeviceQueueFamilyProperties2KHR(device, &mut num, + vk.GetPhysicalDeviceQueueFamilyProperties2KHR(device, + &mut num, families.as_mut_ptr()); - families.into_iter().map(|family| family.queueFamilyProperties).collect() + families + .into_iter() + .map(|family| family.queueFamilyProperties) + .collect() }; let memory: vk::PhysicalDeviceMemoryProperties = unsafe { @@ -340,12 +376,12 @@ impl Instance { }; output.push(PhysicalDeviceInfos { - device: device, - properties: properties, - memory: memory, - queue_families: queue_families, - available_features: Features::from(available_features), - }); + device: device, + properties: properties, + memory: memory, + queue_families: queue_families, + available_features: Features::from(available_features), + }); } output } @@ -498,7 +534,7 @@ impl error::Error for InstanceCreationError { match *self { InstanceCreationError::LoadingError(ref err) => Some(err), InstanceCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -534,7 +570,7 @@ impl From for InstanceCreationError { Error::LayerNotPresent => InstanceCreationError::LayerNotPresent, Error::ExtensionNotPresent => InstanceCreationError::ExtensionNotPresent, Error::IncompatibleDriver => InstanceCreationError::IncompatibleDriver, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -615,9 +651,9 @@ impl<'a> PhysicalDevice<'a> { pub fn from_index(instance: &'a Arc, index: usize) -> Option> { if instance.physical_devices.len() > index { Some(PhysicalDevice { - instance: instance, - device: index, - }) + instance: instance, + device: index, + }) } else { None } @@ -651,11 +687,14 @@ impl<'a> PhysicalDevice<'a> { /// Returns the human-readable name of the device. #[inline] - pub fn name(&self) -> String { // FIXME: for some reason this panics if you use a `&str` + pub fn name(&self) -> String { + // FIXME: for some reason this panics if you use a `&str` unsafe { let val = self.infos().properties.deviceName; let val = CStr::from_ptr(val.as_ptr()); - val.to_str().expect("physical device name contained non-UTF8 characters").to_owned() + val.to_str() + .expect("physical device name contained non-UTF8 characters") + .to_owned() } } @@ -676,13 +715,15 @@ impl<'a> PhysicalDevice<'a> { /// ``` #[inline] pub fn ty(&self) -> PhysicalDeviceType { - match self.instance.physical_devices[self.device].properties.deviceType { + match self.instance.physical_devices[self.device] + .properties + .deviceType { vk::PHYSICAL_DEVICE_TYPE_OTHER => PhysicalDeviceType::Other, vk::PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU => PhysicalDeviceType::IntegratedGpu, vk::PHYSICAL_DEVICE_TYPE_DISCRETE_GPU => PhysicalDeviceType::DiscreteGpu, vk::PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU => PhysicalDeviceType::VirtualGpu, vk::PHYSICAL_DEVICE_TYPE_CPU => PhysicalDeviceType::Cpu, - _ => panic!("Unrecognized Vulkan device type") + _ => panic!("Unrecognized Vulkan device type"), } } @@ -713,9 +754,9 @@ impl<'a> PhysicalDevice<'a> { pub fn queue_family_by_id(&self, id: u32) -> Option> { if (id as usize) < self.infos().queue_families.len() { Some(QueueFamily { - physical_device: *self, - id: id, - }) + physical_device: *self, + id: id, + }) } else { None @@ -736,9 +777,9 @@ impl<'a> PhysicalDevice<'a> { pub fn memory_type_by_id(&self, id: u32) -> Option> { if id < self.infos().memory.memoryTypeCount { Some(MemoryType { - physical_device: *self, - id: id, - }) + physical_device: *self, + id: id, + }) } else { None @@ -759,9 +800,9 @@ impl<'a> PhysicalDevice<'a> { pub fn memory_heap_by_id(&self, id: u32) -> Option> { if id < self.infos().memory.memoryHeapCount { Some(MemoryHeap { - physical_device: *self, - id: id, - }) + physical_device: *self, + id: id, + }) } else { None @@ -803,7 +844,8 @@ impl<'a> PhysicalDevice<'a> { /// Can be stored in a configuration file, so that you can retrieve the device again the next /// time the program is run. #[inline] - pub fn uuid(&self) -> &[u8; 16] { // must be equal to vk::UUID_SIZE + pub fn uuid(&self) -> &[u8; 16] { + // must be equal to vk::UUID_SIZE &self.infos().properties.pipelineCacheUUID } @@ -925,8 +967,7 @@ impl<'a> QueueFamily<'a> { /// > operations are ever added to Vulkan. #[inline] pub fn supports_transfers(&self) -> bool { - (self.flags() & vk::QUEUE_TRANSFER_BIT) != 0 || - self.supports_graphics() || + (self.flags() & vk::QUEUE_TRANSFER_BIT) != 0 || self.supports_graphics() || self.supports_compute() } @@ -976,7 +1017,8 @@ impl<'a> Iterator for QueueFamiliesIter<'a> { } } -impl<'a> ExactSizeIterator for QueueFamiliesIter<'a> {} +impl<'a> ExactSizeIterator for QueueFamiliesIter<'a> { +} /// Represents a memory type in a physical device. #[derive(Debug, Copy, Clone)] @@ -1002,7 +1044,10 @@ impl<'a> MemoryType<'a> { #[inline] pub fn heap(&self) -> MemoryHeap<'a> { let heap_id = self.physical_device.infos().memory.memoryTypes[self.id as usize].heapIndex; - MemoryHeap { physical_device: self.physical_device, id: heap_id } + MemoryHeap { + physical_device: self.physical_device, + id: heap_id, + } } /// Returns true if the memory type is located on the device, which means that it's the most @@ -1087,7 +1132,8 @@ impl<'a> Iterator for MemoryTypesIter<'a> { } } -impl<'a> ExactSizeIterator for MemoryTypesIter<'a> {} +impl<'a> ExactSizeIterator for MemoryTypesIter<'a> { +} /// Represents a memory heap in a physical device. #[derive(Debug, Copy, Clone)] @@ -1156,7 +1202,8 @@ impl<'a> Iterator for MemoryHeapsIter<'a> { } } -impl<'a> ExactSizeIterator for MemoryHeapsIter<'a> {} +impl<'a> ExactSizeIterator for MemoryHeapsIter<'a> { +} /// Limits of a physical device. pub struct Limits<'a> { @@ -1300,12 +1347,12 @@ mod tests { let phys = match instance::PhysicalDevice::enumerate(&instance).next() { Some(p) => p, - None => return + None => return, }; let queue_family = match phys.queue_families().next() { Some(q) => q, - None => return + None => return, }; let by_id = phys.queue_family_by_id(queue_family.id()).unwrap(); diff --git a/vulkano/src/instance/layers.rs b/vulkano/src/instance/layers.rs index b6ae4302..256091dd 100644 --- a/vulkano/src/instance/layers.rs +++ b/vulkano/src/instance/layers.rs @@ -8,18 +8,18 @@ // according to those terms. use std::error; -use std::fmt; use std::ffi::CStr; +use std::fmt; use std::ptr; use std::vec::IntoIter; -use check_errors; -use OomError; use Error; -use vk; +use OomError; +use check_errors; use instance::loader; use instance::loader::LoadingError; use version::Version; +use vk; /// Queries the list of layers that are available when creating an instance. /// @@ -28,7 +28,7 @@ use version::Version; /// to pass its name (returned by `LayerProperties::name()`) when creating the /// [`Instance`](struct.Instance.html). /// -/// This function returns an error if it failed to load the Vulkan library. +/// This function returns an error if it failed to load the Vulkan library. /// /// > **Note**: It is possible that one of the layers enumerated here is no longer available when /// > you create the `Instance`. This will lead to an error when calling `Instance::new`. The @@ -46,22 +46,21 @@ use version::Version; /// ``` pub fn layers_list() -> Result { unsafe { - let entry_points = try!(loader::entry_points()); + let entry_points = loader::entry_points()?; let mut num = 0; - try!(check_errors({ - entry_points.EnumerateInstanceLayerProperties(&mut num, ptr::null_mut()) - })); + check_errors({ + entry_points.EnumerateInstanceLayerProperties(&mut num, ptr::null_mut()) + })?; let mut layers: Vec = Vec::with_capacity(num as usize); - try!(check_errors({ - entry_points.EnumerateInstanceLayerProperties(&mut num, layers.as_mut_ptr()) - })); + check_errors({ + entry_points + .EnumerateInstanceLayerProperties(&mut num, layers.as_mut_ptr()) + })?; layers.set_len(num as usize); - Ok(LayersIterator { - iter: layers.into_iter() - }) + Ok(LayersIterator { iter: layers.into_iter() }) } } @@ -87,7 +86,11 @@ impl LayerProperties { /// ``` #[inline] pub fn name(&self) -> &str { - unsafe { CStr::from_ptr(self.props.layerName.as_ptr()).to_str().unwrap() } + unsafe { + CStr::from_ptr(self.props.layerName.as_ptr()) + .to_str() + .unwrap() + } } /// Returns a description of the layer. @@ -105,7 +108,11 @@ impl LayerProperties { /// ``` #[inline] pub fn description(&self) -> &str { - unsafe { CStr::from_ptr(self.props.description.as_ptr()).to_str().unwrap() } + unsafe { + CStr::from_ptr(self.props.description.as_ptr()) + .to_str() + .unwrap() + } } /// Returns the version of Vulkan supported by this layer. @@ -200,7 +207,7 @@ impl From for LayersListError { match err { err @ Error::OutOfHostMemory => LayersListError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => LayersListError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -208,7 +215,7 @@ impl From for LayersListError { /// Iterator that produces the list of layers that are available. // TODO: #[derive(Debug, Clone)] pub struct LayersIterator { - iter: IntoIter + iter: IntoIter, } impl Iterator for LayersIterator { @@ -236,7 +243,7 @@ mod tests { fn layers_list() { let mut list = match instance::layers_list() { Ok(l) => l, - Err(_) => return + Err(_) => return, }; while let Some(_) = list.next() {} diff --git a/vulkano/src/instance/loader.rs b/vulkano/src/instance/loader.rs index 05116cec..fe690362 100644 --- a/vulkano/src/instance/loader.rs +++ b/vulkano/src/instance/loader.rs @@ -20,22 +20,17 @@ use vk; fn load_static() -> Result { use std::os::raw::c_char; - extern { + extern "C" { fn vkGetInstanceProcAddr(instance: vk::Instance, pName: *const c_char) -> vk::PFN_vkVoidFunction; } extern "system" fn wrapper(instance: vk::Instance, pName: *const c_char) - -> vk::PFN_vkVoidFunction - { - unsafe { - vkGetInstanceProcAddr(instance, pName) - } + -> vk::PFN_vkVoidFunction { + unsafe { vkGetInstanceProcAddr(instance, pName) } } - Ok(vk::Static { - GetInstanceProcAddr: wrapper, - }) + Ok(vk::Static { GetInstanceProcAddr: wrapper }) } #[cfg(not(any(target_os = "macos", target_os = "ios")))] @@ -58,10 +53,11 @@ fn load_static() -> Result { let name = name.to_str().unwrap(); match lib.symbol(name) { Ok(s) => s, - Err(_) => { // TODO: return error? + Err(_) => { + // TODO: return error? err = Some(LoadingError::MissingEntryPoint(name.to_owned())); ptr::null() - } + }, } }); @@ -109,7 +105,7 @@ pub fn entry_points() -> Result<&'static vk::EntryPoints, LoadingError> { #[derive(Debug, Clone)] pub enum LoadingError { /// Failed to load the Vulkan shared library. - LibraryLoadFailure(String), // TODO: meh for error type, but this needs changes in shared_library + LibraryLoadFailure(String), // TODO: meh for error type, but this needs changes in shared_library /// One of the entry points required to be supported by the Vulkan implementation is missing. MissingEntryPoint(String), diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index 54078336..11b61cf9 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -16,7 +16,7 @@ //! ```no_run //! use vulkano::instance::Instance; //! use vulkano::instance::InstanceExtensions; -//! +//! //! let instance = match Instance::new(None, &InstanceExtensions::none(), None) { //! Ok(i) => i, //! Err(err) => panic!("Couldn't build instance: {:?}", err) @@ -88,7 +88,7 @@ //! // Builds an `ApplicationInfo` by looking at the content of the `Cargo.toml` file at //! // compile-time. //! let app_infos = ApplicationInfo::from_cargo_toml(); -//! +//! //! let _instance = Instance::new(Some(&app_infos), &InstanceExtensions::none(), None).unwrap(); //! ``` //! @@ -104,29 +104,30 @@ //! Once you have chosen a physical device, you can create a `Device` object from it. See the //! `device` module for more info. //! -pub use features::Features; + pub use self::extensions::DeviceExtensions; pub use self::extensions::InstanceExtensions; pub use self::extensions::RawDeviceExtensions; pub use self::extensions::RawInstanceExtensions; +pub use self::instance::ApplicationInfo; pub use self::instance::Instance; pub use self::instance::InstanceCreationError; -pub use self::instance::ApplicationInfo; +pub use self::instance::Limits; +pub use self::instance::MemoryHeap; +pub use self::instance::MemoryHeapsIter; +pub use self::instance::MemoryType; +pub use self::instance::MemoryTypesIter; pub use self::instance::PhysicalDevice; -pub use self::instance::PhysicalDevicesIter; pub use self::instance::PhysicalDeviceType; +pub use self::instance::PhysicalDevicesIter; pub use self::instance::QueueFamiliesIter; pub use self::instance::QueueFamily; -pub use self::instance::MemoryTypesIter; -pub use self::instance::MemoryType; -pub use self::instance::MemoryHeapsIter; -pub use self::instance::MemoryHeap; -pub use self::instance::Limits; -pub use self::layers::layers_list; pub use self::layers::LayerProperties; pub use self::layers::LayersIterator; pub use self::layers::LayersListError; +pub use self::layers::layers_list; pub use self::loader::LoadingError; +pub use features::Features; pub use version::Version; pub mod debug; diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index a8fc30ca..fa3c4243 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -58,8 +58,8 @@ //! //#![warn(missing_docs)] // TODO: activate -#![allow(dead_code)] // TODO: remove -#![allow(unused_variables)] // TODO: remove +#![allow(dead_code)] // TODO: remove +#![allow(unused_variables)] // TODO: remove extern crate crossbeam; extern crate fnv; @@ -99,9 +99,12 @@ use std::sync::MutexGuard; /// Alternative to the `Deref` trait. Contrary to `Deref`, must always return the same object. pub unsafe trait SafeDeref: Deref {} -unsafe impl<'a, T: ?Sized> SafeDeref for &'a T {} -unsafe impl SafeDeref for Arc {} -unsafe impl SafeDeref for Box {} +unsafe impl<'a, T: ?Sized> SafeDeref for &'a T { +} +unsafe impl SafeDeref for Arc { +} +unsafe impl SafeDeref for Box { +} /// Gives access to the internal identifier of an object. pub unsafe trait VulkanObject { @@ -154,7 +157,7 @@ impl From for OomError { match err { Error::OutOfHostMemory => OomError::OutOfHostMemory, Error::OutOfDeviceMemory => OomError::OutOfDeviceMemory, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -178,7 +181,7 @@ enum Success { /// panic for error code that arent supposed to happen. #[derive(Debug, Copy, Clone)] #[repr(u32)] -#[doc(hidden)] // TODO: this is necessary because of the stupid visibility rules in rustc +#[doc(hidden)] // TODO: this is necessary because of the stupid visibility rules in rustc pub enum Error { OutOfHostMemory = vk::ERROR_OUT_OF_HOST_MEMORY, OutOfDeviceMemory = vk::ERROR_OUT_OF_DEVICE_MEMORY, @@ -226,7 +229,8 @@ fn check_errors(result: vk::Result) -> Result { vk::ERROR_INCOMPATIBLE_DISPLAY_KHR => Err(Error::IncompatibleDisplay), vk::ERROR_VALIDATION_FAILED_EXT => Err(Error::ValidationFailed), vk::ERROR_OUT_OF_POOL_MEMORY_KHR => Err(Error::OutOfPoolMemory), - vk::ERROR_INVALID_SHADER_NV => panic!("Vulkan function returned VK_ERROR_INVALID_SHADER_NV"), - c => unreachable!("Unexpected error code returned by Vulkan: {}", c) + vk::ERROR_INVALID_SHADER_NV => panic!("Vulkan function returned \ + VK_ERROR_INVALID_SHADER_NV"), + c => unreachable!("Unexpected error code returned by Vulkan: {}", c), } } diff --git a/vulkano/src/memory/device_memory.rs b/vulkano/src/memory/device_memory.rs index 5cb3ea99..d7f43267 100644 --- a/vulkano/src/memory/device_memory.rs +++ b/vulkano/src/memory/device_memory.rs @@ -9,20 +9,20 @@ use std::fmt; use std::mem; -use std::ptr; use std::ops::Deref; use std::ops::DerefMut; use std::ops::Range; use std::os::raw::c_void; +use std::ptr; use std::sync::Arc; -use instance::MemoryType; -use device::Device; -use device::DeviceOwned; -use memory::Content; use OomError; use VulkanObject; use check_errors; +use device::Device; +use device::DeviceOwned; +use instance::MemoryType; +use memory::Content; use vk; /// Represents memory that has been allocated. @@ -36,7 +36,7 @@ use vk; /// /// # let device: std::sync::Arc = return; /// let mem_ty = device.physical_device().memory_types().next().unwrap(); -/// +/// /// // Allocates 1kB of memory. /// let memory = DeviceMemory::alloc(device.clone(), mem_ty, 1024).unwrap(); /// ``` @@ -51,7 +51,7 @@ impl DeviceMemory { /// Allocates a chunk of memory from the device. /// /// Some platforms may have a limit on the maximum size of a single allocation. For example, - /// certain systems may fail to create allocations with a size greater than or equal to 4GB. + /// certain systems may fail to create allocations with a size greater than or equal to 4GB. /// /// # Panic /// @@ -61,8 +61,7 @@ impl DeviceMemory { // TODO: VK_ERROR_TOO_MANY_OBJECTS error #[inline] pub fn alloc(device: Arc, memory_type: MemoryType, size: usize) - -> Result - { + -> Result { assert!(size >= 1); assert_eq!(device.physical_device().internal_object(), memory_type.physical_device().internal_object()); @@ -85,17 +84,19 @@ impl DeviceMemory { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.AllocateMemory(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.AllocateMemory(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(DeviceMemory { - memory: memory, - device: device, - size: size, - memory_type_index: memory_type.id(), - }) + memory: memory, + device: device, + size: size, + memory_type_index: memory_type.id(), + }) } /// Allocates a chunk of memory and maps it. @@ -106,34 +107,39 @@ impl DeviceMemory { /// - Panics if the memory type is not host-visible. /// pub fn alloc_and_map(device: Arc, memory_type: MemoryType, size: usize) - -> Result - { + -> Result { let vk = device.pointers(); assert!(memory_type.is_host_visible()); - let mem = try!(DeviceMemory::alloc(device.clone(), memory_type, size)); + let mem = DeviceMemory::alloc(device.clone(), memory_type, size)?; let coherent = memory_type.is_host_coherent(); let ptr = unsafe { let mut output = mem::uninitialized(); - try!(check_errors(vk.MapMemory(device.internal_object(), mem.memory, 0, - mem.size as vk::DeviceSize, 0 /* reserved flags */, - &mut output))); + check_errors(vk.MapMemory(device.internal_object(), + mem.memory, + 0, + mem.size as vk::DeviceSize, + 0, /* reserved flags */ + &mut output))?; output }; Ok(MappedDeviceMemory { - memory: mem, - pointer: ptr, - coherent: coherent, - }) + memory: mem, + pointer: ptr, + coherent: coherent, + }) } /// Returns the memory type this chunk was allocated on. #[inline] pub fn memory_type(&self) -> MemoryType { - self.device.physical_device().memory_type_by_id(self.memory_type_index).unwrap() + self.device + .physical_device() + .memory_type_by_id(self.memory_type_index) + .unwrap() } /// Returns the size in bytes of that memory chunk. @@ -185,7 +191,7 @@ impl Drop for DeviceMemory { /// is not host-accessible. /// /// In order to access the content of the allocated memory, you can use the `read_write` method. -/// This method returns a guard object that derefs to the content. +/// This method returns a guard object that derefs to the content. /// /// # Example /// @@ -193,7 +199,7 @@ impl Drop for DeviceMemory { /// use vulkano::memory::DeviceMemory; /// /// # let device: std::sync::Arc = return; -/// // The memory type must be mappable. +/// // The memory type must be mappable. /// let mem_ty = device.physical_device().memory_types() /// .filter(|t| t.is_host_visible()) /// .next().unwrap(); // Vk specs guarantee that this can't fail @@ -253,7 +259,8 @@ impl MappedDeviceMemory { { let vk = self.memory.device().pointers(); let pointer = T::ref_from_ptr((self.pointer as usize + range.start) as *mut _, - range.end - range.start).unwrap(); // TODO: error + range.end - range.start) + .unwrap(); // TODO: error if !self.coherent { let range = vk::MappedMemoryRange { @@ -298,8 +305,10 @@ unsafe impl DeviceOwned for MappedDeviceMemory { } } -unsafe impl Send for MappedDeviceMemory {} -unsafe impl Sync for MappedDeviceMemory {} +unsafe impl Send for MappedDeviceMemory { +} +unsafe impl Sync for MappedDeviceMemory { +} impl fmt::Debug for MappedDeviceMemory { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { @@ -334,13 +343,15 @@ impl<'a, T: ?Sized + 'a> CpuAccess<'a, T> { pointer: f(self.pointer), mem: self.mem, coherent: self.coherent, - range: self.range.clone(), // TODO: ? + range: self.range.clone(), // TODO: ? } } } -unsafe impl<'a, T: ?Sized + 'a> Send for CpuAccess<'a, T> {} -unsafe impl<'a, T: ?Sized + 'a> Sync for CpuAccess<'a, T> {} +unsafe impl<'a, T: ?Sized + 'a> Send for CpuAccess<'a, T> { +} +unsafe impl<'a, T: ?Sized + 'a> Sync for CpuAccess<'a, T> { +} impl<'a, T: ?Sized + 'a> Deref for CpuAccess<'a, T> { type Target = T; @@ -375,8 +386,7 @@ impl<'a, T: ?Sized + 'a> Drop for CpuAccess<'a, T> { // TODO: check result? unsafe { - vk.FlushMappedMemoryRanges(self.mem.as_ref().device().internal_object(), - 1, &range); + vk.FlushMappedMemoryRanges(self.mem.as_ref().device().internal_object(), 1, &range); } } } @@ -406,30 +416,38 @@ mod tests { #[cfg(target_pointer_width = "64")] fn oom_single() { let (device, _) = gfx_dev_and_queue!(); - let mem_ty = device.physical_device().memory_types().filter(|m| !m.is_lazily_allocated()) - .next().unwrap(); - + let mem_ty = device + .physical_device() + .memory_types() + .filter(|m| !m.is_lazily_allocated()) + .next() + .unwrap(); + match DeviceMemory::alloc(device.clone(), mem_ty, 0xffffffffffffffff) { Err(OomError::OutOfDeviceMemory) => (), - _ => panic!() + _ => panic!(), } } #[test] - #[ignore] // TODO: test fails for now on Mesa+Intel + #[ignore] // TODO: test fails for now on Mesa+Intel fn oom_multi() { let (device, _) = gfx_dev_and_queue!(); - let mem_ty = device.physical_device().memory_types().filter(|m| !m.is_lazily_allocated()) - .next().unwrap(); + let mem_ty = device + .physical_device() + .memory_types() + .filter(|m| !m.is_lazily_allocated()) + .next() + .unwrap(); let heap_size = mem_ty.heap().size(); let mut allocs = Vec::new(); - + for _ in 0 .. 4 { match DeviceMemory::alloc(device.clone(), mem_ty, heap_size / 3) { Err(OomError::OutOfDeviceMemory) => return, // test succeeded Ok(a) => allocs.push(a), - _ => () + _ => (), } } diff --git a/vulkano/src/memory/mod.rs b/vulkano/src/memory/mod.rs index 81078f3c..19e0ebd1 100644 --- a/vulkano/src/memory/mod.rs +++ b/vulkano/src/memory/mod.rs @@ -66,13 +66,13 @@ //! //! ``` //! use vulkano::memory::DeviceMemory; -//! +//! //! # let device: std::sync::Arc = return; //! // Taking the first memory type for the sake of this example. //! let ty = device.physical_device().memory_types().next().unwrap(); -//! +//! //! let alloc = DeviceMemory::alloc(device.clone(), ty, 1024).expect("Failed to allocate memory"); -//! +//! //! // The memory is automatically free'd when `alloc` is destroyed. //! ``` //! diff --git a/vulkano/src/memory/pool/host_visible.rs b/vulkano/src/memory/pool/host_visible.rs index 8934edeb..1e157f80 100644 --- a/vulkano/src/memory/pool/host_visible.rs +++ b/vulkano/src/memory/pool/host_visible.rs @@ -12,12 +12,12 @@ use std::ops::Range; use std::sync::Arc; use std::sync::Mutex; +use OomError; use device::Device; use instance::Instance; use instance::MemoryType; use memory::DeviceMemory; use memory::MappedDeviceMemory; -use OomError; /// Memory pool that operates on a given memory type. #[derive(Debug)] @@ -36,18 +36,17 @@ impl StdHostVisibleMemoryTypePool { /// - Panics if the `device` and `memory_type` don't belong to the same physical device. /// #[inline] - pub fn new(device: Arc, memory_type: MemoryType) - -> Arc - { + pub fn new(device: Arc, memory_type: MemoryType) -> Arc { assert_eq!(&**device.physical_device().instance() as *const Instance, &**memory_type.physical_device().instance() as *const Instance); - assert_eq!(device.physical_device().index(), memory_type.physical_device().index()); + assert_eq!(device.physical_device().index(), + memory_type.physical_device().index()); Arc::new(StdHostVisibleMemoryTypePool { - device: device.clone(), - memory_type: memory_type.id(), - occupied: Mutex::new(Vec::new()), - }) + device: device.clone(), + memory_type: memory_type.id(), + occupied: Mutex::new(Vec::new()), + }) } /// Allocates memory from the pool. @@ -58,12 +57,14 @@ impl StdHostVisibleMemoryTypePool { /// - Panics if `alignment` is 0. /// pub fn alloc(me: &Arc, size: usize, alignment: usize) - -> Result - { + -> Result { assert!(size != 0); assert!(alignment != 0); - #[inline] fn align(val: usize, al: usize) -> usize { al * (1 + (val - 1) / al) } + #[inline] + fn align(val: usize, al: usize) -> usize { + al * (1 + (val - 1) / al) + } // Find a location. let mut occupied = me.occupied.lock().unwrap(); @@ -78,11 +79,11 @@ impl StdHostVisibleMemoryTypePool { if entry1_end + size <= entry2.start { entries.insert(i + 1, entry1_end .. entry1_end + size); return Ok(StdHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: dev_mem.clone(), - offset: entry1_end, - size: size, - }); + pool: me.clone(), + memory: dev_mem.clone(), + offset: entry1_end, + size: size, + }); } } @@ -91,29 +92,30 @@ impl StdHostVisibleMemoryTypePool { if last_end + size <= (**dev_mem).as_ref().size() { entries.push(last_end .. last_end + size); return Ok(StdHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: dev_mem.clone(), - offset: last_end, - size: size, - }); + pool: me.clone(), + memory: dev_mem.clone(), + offset: last_end, + size: size, + }); } } // We need to allocate a new block. let new_block = { - const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB + const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB let to_alloc = cmp::max(MIN_BLOCK_SIZE, size.next_power_of_two()); - let new_block = try!(DeviceMemory::alloc_and_map(me.device.clone(), me.memory_type(), to_alloc)); + let new_block = + DeviceMemory::alloc_and_map(me.device.clone(), me.memory_type(), to_alloc)?; Arc::new(new_block) }; occupied.push((new_block.clone(), vec![0 .. size])); Ok(StdHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: new_block, - offset: 0, - size: size, - }) + pool: me.clone(), + memory: new_block, + offset: 0, + size: size, + }) } /// Returns the device this pool operates on. @@ -125,7 +127,10 @@ impl StdHostVisibleMemoryTypePool { /// Returns the memory type this pool operates on. #[inline] pub fn memory_type(&self) -> MemoryType { - self.device.physical_device().memory_type_by_id(self.memory_type).unwrap() + self.device + .physical_device() + .memory_type_by_id(self.memory_type) + .unwrap() } } @@ -158,8 +163,10 @@ impl Drop for StdHostVisibleMemoryTypePoolAlloc { fn drop(&mut self) { let mut occupied = self.pool.occupied.lock().unwrap(); - let entries = occupied.iter_mut() - .find(|e| &*e.0 as *const MappedDeviceMemory == &*self.memory).unwrap(); + let entries = occupied + .iter_mut() + .find(|e| &*e.0 as *const MappedDeviceMemory == &*self.memory) + .unwrap(); entries.1.retain(|e| e.start != self.offset); } diff --git a/vulkano/src/memory/pool/mod.rs b/vulkano/src/memory/pool/mod.rs index 6fe3fefd..0af0d212 100644 --- a/vulkano/src/memory/pool/mod.rs +++ b/vulkano/src/memory/pool/mod.rs @@ -7,17 +7,17 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use OomError; use instance::MemoryType; use memory::DeviceMemory; use memory::MappedDeviceMemory; -use OomError; -pub use self::pool::StdMemoryPool; -pub use self::pool::StdMemoryPoolAlloc; pub use self::host_visible::StdHostVisibleMemoryTypePool; pub use self::host_visible::StdHostVisibleMemoryTypePoolAlloc; pub use self::non_host_visible::StdNonHostVisibleMemoryTypePool; pub use self::non_host_visible::StdNonHostVisibleMemoryTypePoolAlloc; +pub use self::pool::StdMemoryPool; +pub use self::pool::StdMemoryPoolAlloc; mod host_visible; mod non_host_visible; diff --git a/vulkano/src/memory/pool/non_host_visible.rs b/vulkano/src/memory/pool/non_host_visible.rs index ec57a63c..5b460f87 100644 --- a/vulkano/src/memory/pool/non_host_visible.rs +++ b/vulkano/src/memory/pool/non_host_visible.rs @@ -12,11 +12,11 @@ use std::ops::Range; use std::sync::Arc; use std::sync::Mutex; +use OomError; use device::Device; use instance::Instance; use instance::MemoryType; use memory::DeviceMemory; -use OomError; /// Memory pool that operates on a given memory type. #[derive(Debug)] @@ -36,17 +36,17 @@ impl StdNonHostVisibleMemoryTypePool { /// #[inline] pub fn new(device: Arc, memory_type: MemoryType) - -> Arc - { + -> Arc { assert_eq!(&**device.physical_device().instance() as *const Instance, &**memory_type.physical_device().instance() as *const Instance); - assert_eq!(device.physical_device().index(), memory_type.physical_device().index()); + assert_eq!(device.physical_device().index(), + memory_type.physical_device().index()); Arc::new(StdNonHostVisibleMemoryTypePool { - device: device.clone(), - memory_type: memory_type.id(), - occupied: Mutex::new(Vec::new()), - }) + device: device.clone(), + memory_type: memory_type.id(), + occupied: Mutex::new(Vec::new()), + }) } /// Allocates memory from the pool. @@ -57,12 +57,14 @@ impl StdNonHostVisibleMemoryTypePool { /// - Panics if `alignment` is 0. /// pub fn alloc(me: &Arc, size: usize, alignment: usize) - -> Result - { + -> Result { assert!(size != 0); assert!(alignment != 0); - #[inline] fn align(val: usize, al: usize) -> usize { al * (1 + (val - 1) / al) } + #[inline] + fn align(val: usize, al: usize) -> usize { + al * (1 + (val - 1) / al) + } // Find a location. let mut occupied = me.occupied.lock().unwrap(); @@ -77,11 +79,11 @@ impl StdNonHostVisibleMemoryTypePool { if entry1_end + size <= entry2.start { entries.insert(i + 1, entry1_end .. entry1_end + size); return Ok(StdNonHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: dev_mem.clone(), - offset: entry1_end, - size: size, - }); + pool: me.clone(), + memory: dev_mem.clone(), + offset: entry1_end, + size: size, + }); } } @@ -90,29 +92,29 @@ impl StdNonHostVisibleMemoryTypePool { if last_end + size <= dev_mem.size() { entries.push(last_end .. last_end + size); return Ok(StdNonHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: dev_mem.clone(), - offset: last_end, - size: size, - }); + pool: me.clone(), + memory: dev_mem.clone(), + offset: last_end, + size: size, + }); } } // We need to allocate a new block. let new_block = { - const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB + const MIN_BLOCK_SIZE: usize = 8 * 1024 * 1024; // 8 MB let to_alloc = cmp::max(MIN_BLOCK_SIZE, size.next_power_of_two()); - let new_block = try!(DeviceMemory::alloc(me.device.clone(), me.memory_type(), to_alloc)); + let new_block = DeviceMemory::alloc(me.device.clone(), me.memory_type(), to_alloc)?; Arc::new(new_block) }; occupied.push((new_block.clone(), vec![0 .. size])); Ok(StdNonHostVisibleMemoryTypePoolAlloc { - pool: me.clone(), - memory: new_block, - offset: 0, - size: size, - }) + pool: me.clone(), + memory: new_block, + offset: 0, + size: size, + }) } /// Returns the device this pool operates on. @@ -124,7 +126,10 @@ impl StdNonHostVisibleMemoryTypePool { /// Returns the memory type this pool operates on. #[inline] pub fn memory_type(&self) -> MemoryType { - self.device.physical_device().memory_type_by_id(self.memory_type).unwrap() + self.device + .physical_device() + .memory_type_by_id(self.memory_type) + .unwrap() } } @@ -157,8 +162,10 @@ impl Drop for StdNonHostVisibleMemoryTypePoolAlloc { fn drop(&mut self) { let mut occupied = self.pool.occupied.lock().unwrap(); - let entries = occupied.iter_mut() - .find(|e| &*e.0 as *const DeviceMemory == &*self.memory).unwrap(); + let entries = occupied + .iter_mut() + .find(|e| &*e.0 as *const DeviceMemory == &*self.memory) + .unwrap(); entries.1.retain(|e| e.start != self.offset); } diff --git a/vulkano/src/memory/pool/pool.rs b/vulkano/src/memory/pool/pool.rs index 5740005d..90f31935 100644 --- a/vulkano/src/memory/pool/pool.rs +++ b/vulkano/src/memory/pool/pool.rs @@ -7,15 +7,18 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use fnv::FnvHasher; use std::collections::HashMap; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; use std::sync::Arc; use std::sync::Mutex; -use fnv::FnvHasher; +use OomError; use device::Device; use instance::MemoryType; +use memory::DeviceMemory; +use memory::MappedDeviceMemory; use memory::pool::AllocLayout; use memory::pool::MemoryPool; use memory::pool::MemoryPoolAlloc; @@ -23,9 +26,6 @@ use memory::pool::StdHostVisibleMemoryTypePool; use memory::pool::StdHostVisibleMemoryTypePoolAlloc; use memory::pool::StdNonHostVisibleMemoryTypePool; use memory::pool::StdNonHostVisibleMemoryTypePoolAlloc; -use memory::DeviceMemory; -use memory::MappedDeviceMemory; -use OomError; #[derive(Debug)] pub struct StdMemoryPool { @@ -43,32 +43,37 @@ impl StdMemoryPool { let hasher = BuildHasherDefault::::default(); Arc::new(StdMemoryPool { - device: device.clone(), - pools: Mutex::new(HashMap::with_capacity_and_hasher(cap, hasher)), - }) + device: device.clone(), + pools: Mutex::new(HashMap::with_capacity_and_hasher(cap, hasher)), + }) } } unsafe impl MemoryPool for Arc { type Alloc = StdMemoryPoolAlloc; - fn alloc(&self, memory_type: MemoryType, size: usize, alignment: usize, - layout: AllocLayout) -> Result - { + fn alloc(&self, memory_type: MemoryType, size: usize, alignment: usize, layout: AllocLayout) + -> Result { let mut pools = self.pools.lock().unwrap(); match pools.entry((memory_type.id(), layout)) { Entry::Occupied(entry) => { match entry.get() { &Pool::HostVisible(ref pool) => { - let alloc = try!(StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)); + let alloc = StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?; let inner = StdMemoryPoolAllocInner::HostVisible(alloc); - Ok(StdMemoryPoolAlloc { inner: inner, pool: self.clone() }) + Ok(StdMemoryPoolAlloc { + inner: inner, + pool: self.clone(), + }) }, &Pool::NonHostVisible(ref pool) => { - let alloc = try!(StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)); + let alloc = StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?; let inner = StdMemoryPoolAllocInner::NonHostVisible(alloc); - Ok(StdMemoryPoolAlloc { inner: inner, pool: self.clone() }) + Ok(StdMemoryPoolAlloc { + inner: inner, + pool: self.clone(), + }) }, } }, @@ -76,18 +81,26 @@ unsafe impl MemoryPool for Arc { Entry::Vacant(entry) => { match memory_type.is_host_visible() { true => { - let pool = StdHostVisibleMemoryTypePool::new(self.device.clone(), memory_type); + let pool = StdHostVisibleMemoryTypePool::new(self.device.clone(), + memory_type); entry.insert(Pool::HostVisible(pool.clone())); - let alloc = try!(StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)); + let alloc = StdHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?; let inner = StdMemoryPoolAllocInner::HostVisible(alloc); - Ok(StdMemoryPoolAlloc { inner: inner, pool: self.clone() }) + Ok(StdMemoryPoolAlloc { + inner: inner, + pool: self.clone(), + }) }, false => { - let pool = StdNonHostVisibleMemoryTypePool::new(self.device.clone(), memory_type); + let pool = StdNonHostVisibleMemoryTypePool::new(self.device.clone(), + memory_type); entry.insert(Pool::NonHostVisible(pool.clone())); - let alloc = try!(StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)); + let alloc = StdNonHostVisibleMemoryTypePool::alloc(&pool, size, alignment)?; let inner = StdMemoryPoolAllocInner::NonHostVisible(alloc); - Ok(StdMemoryPoolAlloc { inner: inner, pool: self.clone() }) + Ok(StdMemoryPoolAlloc { + inner: inner, + pool: self.clone(), + }) }, } }, diff --git a/vulkano/src/pipeline/blend.rs b/vulkano/src/pipeline/blend.rs index 6c1af8ac..fd36d4ea 100644 --- a/vulkano/src/pipeline/blend.rs +++ b/vulkano/src/pipeline/blend.rs @@ -165,10 +165,18 @@ impl Into for AttachmentBlend { alphaBlendOp: self.alpha_op as u32, colorWriteMask: { let mut mask = 0; - if self.mask_red { mask |= vk::COLOR_COMPONENT_R_BIT; } - if self.mask_green { mask |= vk::COLOR_COMPONENT_G_BIT; } - if self.mask_blue { mask |= vk::COLOR_COMPONENT_B_BIT; } - if self.mask_alpha { mask |= vk::COLOR_COMPONENT_A_BIT; } + if self.mask_red { + mask |= vk::COLOR_COMPONENT_R_BIT; + } + if self.mask_green { + mask |= vk::COLOR_COMPONENT_G_BIT; + } + if self.mask_blue { + mask |= vk::COLOR_COMPONENT_B_BIT; + } + if self.mask_alpha { + mask |= vk::COLOR_COMPONENT_A_BIT; + } mask }, } diff --git a/vulkano/src/pipeline/cache.rs b/vulkano/src/pipeline/cache.rs index f6a98134..2d5fcf72 100644 --- a/vulkano/src/pipeline/cache.rs +++ b/vulkano/src/pipeline/cache.rs @@ -8,20 +8,21 @@ // according to those terms. //! Cache the pipeline objects to disk for faster reloads. -//! +//! //! A pipeline cache is an opaque type that allow you to cache your graphics and compute //! pipelines on the disk. -//! +//! //! You can create either an empty cache or a cache from some initial data. Whenever you create a //! graphics or compute pipeline, you have the possibility to pass a reference to that cache. //! TODO: ^ that's not the case yet //! The Vulkan implementation will then look in the cache for an existing entry, or add one if it //! doesn't exist. -//! +//! //! Once that is done, you can extract the data from the cache and store it. See the documentation //! of [`get_data`](struct.PipelineCache.html#method.get_data) for example of how to store the data //! on the disk, and [`with_data`](struct.PipelineCache.html#method.with_data) for how to reload it. //! + use std::mem; use std::ptr; use std::sync::Arc; @@ -82,8 +83,7 @@ impl PipelineCache { /// ``` #[inline] pub unsafe fn with_data(device: Arc, initial_data: &[u8]) - -> Result, OomError> - { + -> Result, OomError> { PipelineCache::new_impl(device, Some(initial_data)) } @@ -105,29 +105,32 @@ impl PipelineCache { // Actual implementation of the constructor. unsafe fn new_impl(device: Arc, initial_data: Option<&[u8]>) - -> Result, OomError> - { + -> Result, OomError> { let vk = device.pointers(); let cache = { let infos = vk::PipelineCacheCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved initialDataSize: initial_data.map(|d| d.len()).unwrap_or(0), - pInitialData: initial_data.map(|d| d.as_ptr() as *const _).unwrap_or(ptr::null()), + pInitialData: initial_data + .map(|d| d.as_ptr() as *const _) + .unwrap_or(ptr::null()), }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreatePipelineCache(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreatePipelineCache(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(PipelineCache { - device: device.clone(), - cache: cache, - })) + device: device.clone(), + cache: cache, + })) } /// Merges other pipeline caches into this one. @@ -146,13 +149,18 @@ impl PipelineCache { unsafe { let vk = self.device.pointers(); - let pipelines = pipelines.into_iter().map(|pipeline| { - assert!(&***pipeline as *const _ != &*self as *const _); - pipeline.cache - }).collect::>(); + let pipelines = pipelines + .into_iter() + .map(|pipeline| { + assert!(&***pipeline as *const _ != &*self as *const _); + pipeline.cache + }) + .collect::>(); - try!(check_errors(vk.MergePipelineCaches(self.device.internal_object(), self.cache, - pipelines.len() as u32, pipelines.as_ptr()))); + check_errors(vk.MergePipelineCaches(self.device.internal_object(), + self.cache, + pipelines.len() as u32, + pipelines.as_ptr()))?; Ok(()) } @@ -191,12 +199,16 @@ impl PipelineCache { let vk = self.device.pointers(); let mut num = 0; - try!(check_errors(vk.GetPipelineCacheData(self.device.internal_object(), self.cache, - &mut num, ptr::null_mut()))); + check_errors(vk.GetPipelineCacheData(self.device.internal_object(), + self.cache, + &mut num, + ptr::null_mut()))?; let mut data: Vec = Vec::with_capacity(num as usize); - try!(check_errors(vk.GetPipelineCacheData(self.device.internal_object(), self.cache, - &mut num, data.as_mut_ptr() as *mut _))); + check_errors(vk.GetPipelineCacheData(self.device.internal_object(), + self.cache, + &mut num, + data.as_mut_ptr() as *mut _))?; data.set_len(num as usize); Ok(data) diff --git a/vulkano/src/pipeline/compute_pipeline.rs b/vulkano/src/pipeline/compute_pipeline.rs index 1041ccbb..3b328c63 100644 --- a/vulkano/src/pipeline/compute_pipeline.rs +++ b/vulkano/src/pipeline/compute_pipeline.rs @@ -17,24 +17,24 @@ use std::sync::Arc; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; use descriptor::pipeline_layout::PipelineLayout; -use descriptor::pipeline_layout::PipelineLayoutSys; +use descriptor::pipeline_layout::PipelineLayoutAbstract; use descriptor::pipeline_layout::PipelineLayoutCreationError; use descriptor::pipeline_layout::PipelineLayoutDesc; use descriptor::pipeline_layout::PipelineLayoutDescNames; use descriptor::pipeline_layout::PipelineLayoutDescPcRange; -use descriptor::pipeline_layout::PipelineLayoutSuperset; -use descriptor::pipeline_layout::PipelineLayoutAbstract; use descriptor::pipeline_layout::PipelineLayoutNotSupersetError; +use descriptor::pipeline_layout::PipelineLayoutSuperset; +use descriptor::pipeline_layout::PipelineLayoutSys; use pipeline::shader::ComputeShaderEntryPoint; use pipeline::shader::SpecializationConstants; -use device::Device; -use device::DeviceOwned; use Error; use OomError; use SafeDeref; use VulkanObject; use check_errors; +use device::Device; +use device::DeviceOwned; use vk; /// A pipeline object that describes to the Vulkan implementation how it should perform compute @@ -56,15 +56,17 @@ struct Inner { impl ComputePipeline<()> { /// Builds a new `ComputePipeline`. - pub fn new(device: Arc, shader: &ComputeShaderEntryPoint, - specialization: &Css) - -> Result>, ComputePipelineCreationError> + pub fn new( + device: Arc, shader: &ComputeShaderEntryPoint, specialization: &Css) + -> Result>, ComputePipelineCreationError> where Csl: PipelineLayoutDescNames + Clone, Css: SpecializationConstants { unsafe { let pipeline_layout = shader.layout().clone().build(device.clone())?; - ComputePipeline::with_unchecked_pipeline_layout(device, shader, specialization, + ComputePipeline::with_unchecked_pipeline_layout(device, + shader, + specialization, pipeline_layout) } } @@ -75,32 +77,32 @@ impl ComputePipeline { /// /// An error will be returned if the pipeline layout isn't a superset of what the shader /// uses. - pub fn with_pipeline_layout(device: Arc, - shader: &ComputeShaderEntryPoint, - specialization: &Css, - pipeline_layout: Pl) - -> Result, ComputePipelineCreationError> + pub fn with_pipeline_layout( + device: Arc, shader: &ComputeShaderEntryPoint, specialization: &Css, + pipeline_layout: Pl) + -> Result, ComputePipelineCreationError> where Csl: PipelineLayoutDescNames + Clone, Css: SpecializationConstants, - Pl: PipelineLayoutAbstract, + Pl: PipelineLayoutAbstract { unsafe { PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, shader.layout())?; - ComputePipeline::with_unchecked_pipeline_layout(device, shader, specialization, + ComputePipeline::with_unchecked_pipeline_layout(device, + shader, + specialization, pipeline_layout) } } /// Same as `with_pipeline_layout`, but doesn't check whether the pipeline layout is a /// superset of what the shader expects. - pub unsafe fn with_unchecked_pipeline_layout(device: Arc, - shader: &ComputeShaderEntryPoint, - specialization: &Css, - pipeline_layout: Pl) - -> Result, ComputePipelineCreationError> + pub unsafe fn with_unchecked_pipeline_layout( + device: Arc, shader: &ComputeShaderEntryPoint, specialization: &Css, + pipeline_layout: Pl) + -> Result, ComputePipelineCreationError> where Csl: PipelineLayoutDescNames + Clone, Css: SpecializationConstants, - Pl: PipelineLayoutAbstract, + Pl: PipelineLayoutAbstract { let vk = device.pointers(); @@ -138,18 +140,22 @@ impl ComputePipeline { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0, - 1, &infos, ptr::null(), &mut output))); + check_errors(vk.CreateComputePipelines(device.internal_object(), + 0, + 1, + &infos, + ptr::null(), + &mut output))?; output }; Ok(ComputePipeline { - inner: Inner { - device: device.clone(), - pipeline: pipeline, - }, - pipeline_layout: pipeline_layout, - }) + inner: Inner { + device: device.clone(), + pipeline: pipeline, + }, + pipeline_layout: pipeline_layout, + }) } } @@ -190,7 +196,8 @@ unsafe impl ComputePipelineAbstract for ComputePipeline } unsafe impl ComputePipelineAbstract for T - where T: SafeDeref, T::Target: ComputePipelineAbstract + where T: SafeDeref, + T::Target: ComputePipelineAbstract { #[inline] fn inner(&self) -> ComputePipelineSys { @@ -212,7 +219,9 @@ unsafe impl<'a> VulkanObject for ComputePipelineSys<'a> { } } -unsafe impl PipelineLayoutAbstract for ComputePipeline where Pl: PipelineLayoutAbstract { +unsafe impl PipelineLayoutAbstract for ComputePipeline + where Pl: PipelineLayoutAbstract +{ #[inline] fn sys(&self) -> PipelineLayoutSys { self.layout().sys() @@ -224,7 +233,9 @@ unsafe impl PipelineLayoutAbstract for ComputePipeline where Pl: Pipelin } } -unsafe impl PipelineLayoutDesc for ComputePipeline where Pl: PipelineLayoutDesc { +unsafe impl PipelineLayoutDesc for ComputePipeline + where Pl: PipelineLayoutDesc +{ #[inline] fn num_sets(&self) -> usize { self.pipeline_layout.num_sets() @@ -251,7 +262,9 @@ unsafe impl PipelineLayoutDesc for ComputePipeline where Pl: PipelineLay } } -unsafe impl PipelineLayoutDescNames for ComputePipeline where Pl: PipelineLayoutDescNames { +unsafe impl PipelineLayoutDescNames for ComputePipeline + where Pl: PipelineLayoutDescNames +{ #[inline] fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { self.pipeline_layout.descriptor_by_name(name) @@ -301,12 +314,10 @@ impl error::Error for ComputePipelineCreationError { fn description(&self) -> &str { match *self { ComputePipelineCreationError::OomError(_) => "not enough memory available", - ComputePipelineCreationError::PipelineLayoutCreationError(_) => "error while creating \ - the pipeline layout \ - object", - ComputePipelineCreationError::IncompatiblePipelineLayout(_) => "the pipeline layout is \ - not compatible with what \ - the shader expects", + ComputePipelineCreationError::PipelineLayoutCreationError(_) => + "error while creating the pipeline layout object", + ComputePipelineCreationError::IncompatiblePipelineLayout(_) => + "the pipeline layout is not compatible with what the shader expects", } } @@ -358,7 +369,7 @@ impl From for ComputePipelineCreationError { err @ Error::OutOfDeviceMemory => { ComputePipelineCreationError::OomError(OomError::from(err)) }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } diff --git a/vulkano/src/pipeline/depth_stencil.rs b/vulkano/src/pipeline/depth_stencil.rs index 0e576e09..e8711009 100644 --- a/vulkano/src/pipeline/depth_stencil.rs +++ b/vulkano/src/pipeline/depth_stencil.rs @@ -8,14 +8,14 @@ // according to those terms. //! Depth and stencil operations description. -//! +//! //! After the fragment shader has finished running, each fragment goes through the depth //! and stencil tests. -//! +//! //! The depth test passes of fails depending on how the depth value of each fragment compares //! to the existing depth value in the depth buffer at that fragment's location. Depth values //! are always between 0.0 and 1.0. -//! +//! //! The stencil test passes or fails depending on how a reference value compares to the existing //! value in the stencil buffer at each fragment's location. Depending on the outcome of the //! depth and stencil tests, the value of the stencil buffer at that location can be updated. @@ -135,10 +135,10 @@ impl Stencil { pub fn always_keep(&self) -> bool { match self.compare { Compare::Always => self.pass_op == StencilOp::Keep && - self.depth_fail_op == StencilOp::Keep, + self.depth_fail_op == StencilOp::Keep, Compare::Never => self.fail_op == StencilOp::Keep, _ => self.pass_op == StencilOp::Keep && self.fail_op == StencilOp::Keep && - self.depth_fail_op == StencilOp::Keep, + self.depth_fail_op == StencilOp::Keep, } } } @@ -178,7 +178,7 @@ pub enum DepthBounds { /// The test is disabled. All fragments pass the depth bounds test. Disabled, - /// Fragments that are within the given range do pass the test. Values are depth values + /// Fragments that are within the given range do pass the test. Values are depth values /// between 0.0 and 1.0. Fixed(Range), diff --git a/vulkano/src/pipeline/graphics_pipeline/builder.rs b/vulkano/src/pipeline/graphics_pipeline/builder.rs index 52e7f06a..26ac751d 100644 --- a/vulkano/src/pipeline/graphics_pipeline/builder.rs +++ b/vulkano/src/pipeline/graphics_pipeline/builder.rs @@ -11,7 +11,6 @@ // to avoid duplicating code, so we hide the warnings for now #![allow(deprecated)] -use std::sync::Arc; use descriptor::pipeline_layout::EmptyPipelineDesc; use descriptor::pipeline_layout::PipelineLayoutAbstract; use descriptor::pipeline_layout::PipelineLayoutDescNames; @@ -19,9 +18,9 @@ use device::Device; use framebuffer::RenderPassAbstract; use framebuffer::RenderPassSubpassInterface; use framebuffer::Subpass; -use pipeline::blend::Blend; -use pipeline::blend::AttachmentsBlend; use pipeline::blend::AttachmentBlend; +use pipeline::blend::AttachmentsBlend; +use pipeline::blend::Blend; use pipeline::blend::LogicOp; use pipeline::depth_stencil::DepthStencil; use pipeline::graphics_pipeline::GraphicsPipeline; @@ -36,23 +35,46 @@ use pipeline::raster::FrontFace; use pipeline::raster::PolygonMode; use pipeline::raster::Rasterization; use pipeline::shader::EmptyShaderInterfaceDef; +use pipeline::shader::FragmentShaderEntryPoint; +use pipeline::shader::GeometryShaderEntryPoint; use pipeline::shader::ShaderInterfaceDef; use pipeline::shader::ShaderInterfaceDefMatch; -use pipeline::shader::VertexShaderEntryPoint; use pipeline::shader::TessControlShaderEntryPoint; use pipeline::shader::TessEvaluationShaderEntryPoint; -use pipeline::shader::GeometryShaderEntryPoint; -use pipeline::shader::FragmentShaderEntryPoint; +use pipeline::shader::VertexShaderEntryPoint; use pipeline::vertex::SingleBufferDefinition; use pipeline::vertex::VertexDefinition; use pipeline::viewport::Scissor; use pipeline::viewport::Viewport; use pipeline::viewport::ViewportsState; +use std::sync::Arc; /// Prototype for a `GraphicsPipeline`. // TODO: we can optimize this by filling directly the raw vk structs -pub struct GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, - Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> { +pub struct GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> +{ vertex_input: Vdef, vertex_shader: Option>, input_assembly: InputAssembly, @@ -67,18 +89,34 @@ pub struct GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl render_pass: Option>, } -impl<'a> GraphicsPipelineBuilder<'a, SingleBufferDefinition<()>, (), (), (), (), (), - EmptyShaderInterfaceDef, EmptyShaderInterfaceDef, - EmptyPipelineDesc, (), EmptyShaderInterfaceDef, - EmptyShaderInterfaceDef, EmptyPipelineDesc, (), - EmptyShaderInterfaceDef, EmptyShaderInterfaceDef, - EmptyPipelineDesc, (), EmptyShaderInterfaceDef, - EmptyShaderInterfaceDef, EmptyPipelineDesc, ()> -{ +impl<'a> + GraphicsPipelineBuilder<'a, + SingleBufferDefinition<()>, + (), + (), + (), + (), + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + ()> { /// Builds a new empty builder. pub(super) fn new() -> Self { GraphicsPipelineBuilder { - vertex_input: SingleBufferDefinition::new(), // TODO: should be empty attrs instead + vertex_input: SingleBufferDefinition::new(), // TODO: should be empty attrs instead vertex_shader: None, input_assembly: InputAssembly::triangle_list(), tessellation: None, @@ -94,16 +132,58 @@ impl<'a> GraphicsPipelineBuilder<'a, SingleBufferDefinition<()>, (), (), (), (), } } -impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, Fs, Fi, - Fo, Fl, Rp> - GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, - Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> +impl<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> + GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> where Vdef: VertexDefinition, - Vl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Fl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Tcl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Tel: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Gl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Vl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Fl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Tcl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Tel: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Gl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required Tci: ShaderInterfaceDefMatch, Tei: ShaderInterfaceDefMatch, Gi: ShaderInterfaceDefMatch + ShaderInterfaceDefMatch, @@ -111,46 +191,128 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Tco: ShaderInterfaceDef, Teo: ShaderInterfaceDef, Go: ShaderInterfaceDef, - Fi: ShaderInterfaceDefMatch + ShaderInterfaceDefMatch + ShaderInterfaceDefMatch, + Fi: ShaderInterfaceDefMatch + + ShaderInterfaceDefMatch + + ShaderInterfaceDefMatch, Fo: ShaderInterfaceDef, - Rp: RenderPassAbstract + RenderPassSubpassInterface, + Rp: RenderPassAbstract + RenderPassSubpassInterface { /// Builds the graphics pipeline. // TODO: replace Box with a PipelineUnion struct without template params - pub fn build(self, device: Arc) -> Result, Rp>, GraphicsPipelineCreationError> { + pub fn build(self, device: Arc) + -> Result, Rp>, + GraphicsPipelineCreationError> { // TODO: return errors instead of panicking if missing param - GraphicsPipeline::with_tessellation_and_geometry(device, GraphicsPipelineParams { - vertex_input: self.vertex_input, - vertex_shader: self.vertex_shader.expect("Vertex shader not specified in the builder"), - input_assembly: self.input_assembly, - tessellation: self.tessellation, - geometry_shader: self.geometry_shader, - viewport: self.viewport.expect("Viewport state not specified in the builder"), - raster: self.raster, - multisample: self.multisample, - fragment_shader: self.fragment_shader.expect("Fragment shader not specified in the builder"), - depth_stencil: self.depth_stencil, - blend: self.blend, - render_pass: self.render_pass.expect("Render pass not specified in the builder"), - }) + GraphicsPipeline::with_tessellation_and_geometry(device, + GraphicsPipelineParams { + vertex_input: self.vertex_input, + vertex_shader: + self.vertex_shader + .expect("Vertex shader not \ + specified in the \ + builder"), + input_assembly: self.input_assembly, + tessellation: self.tessellation, + geometry_shader: self.geometry_shader, + viewport: + self.viewport + .expect("Viewport state not \ + specified in the \ + builder"), + raster: self.raster, + multisample: self.multisample, + fragment_shader: + self.fragment_shader + .expect("Fragment shader not \ + specified in the \ + builder"), + depth_stencil: self.depth_stencil, + blend: self.blend, + render_pass: + self.render_pass + .expect("Render pass not \ + specified in the \ + builder"), + }) } - + // TODO: add build_with_cache method } -impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, Fs, Fi, - Fo, Fl, Rp> - GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, - Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> -{ +impl<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> + GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> { // TODO: add pipeline derivate system /// Sets the vertex input. #[inline] pub fn vertex_input(self, vertex_input: T) - -> GraphicsPipelineBuilder<'a, T, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, - Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> - { + -> GraphicsPipelineBuilder<'a, + T, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> { GraphicsPipelineBuilder { vertex_input: vertex_input, vertex_shader: self.vertex_shader, @@ -173,20 +335,61 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, /// vertex. #[inline] pub fn vertex_input_single_buffer(self) - -> GraphicsPipelineBuilder<'a, SingleBufferDefinition, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, - Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> - { + -> GraphicsPipelineBuilder<'a, + SingleBufferDefinition, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> { self.vertex_input(SingleBufferDefinition::::new()) } /// Sets the vertex shader to use. // TODO: correct specialization constants #[inline] - pub fn vertex_shader(self, shader: VertexShaderEntryPoint<'a, (), Vi2, Vo2, Vl2>, + pub fn vertex_shader(self, + shader: VertexShaderEntryPoint<'a, (), Vi2, Vo2, Vl2>, specialization_constants: ()) - -> GraphicsPipelineBuilder<'a, Vdef, (), Vi2, Vo2, Vl2, Tcs, Tci, Tco, - Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> - { + -> GraphicsPipelineBuilder<'a, + Vdef, + (), + Vi2, + Vo2, + Vl2, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> { GraphicsPipelineBuilder { vertex_input: self.vertex_input, vertex_shader: Some(shader), @@ -225,7 +428,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn point_list(self) -> Self { self.primitive_topology(PrimitiveTopology::PointList) } - + /// Sets the topology of the primitives to a list of lines. /// /// > **Note**: This is equivalent to @@ -234,7 +437,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn line_list(self) -> Self { self.primitive_topology(PrimitiveTopology::LineList) } - + /// Sets the topology of the primitives to a line strip. /// /// > **Note**: This is equivalent to @@ -243,7 +446,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn line_strip(self) -> Self { self.primitive_topology(PrimitiveTopology::LineStrip) } - + /// Sets the topology of the primitives to a list of triangles. Note that this is the default. /// /// > **Note**: This is equivalent to @@ -252,7 +455,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn triangle_list(self) -> Self { self.primitive_topology(PrimitiveTopology::TriangleList) } - + /// Sets the topology of the primitives to a triangle strip. /// /// > **Note**: This is equivalent to @@ -261,7 +464,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn triangle_strip(self) -> Self { self.primitive_topology(PrimitiveTopology::TriangleStrip) } - + /// Sets the topology of the primitives to a fan of triangles. /// /// > **Note**: This is equivalent to @@ -270,7 +473,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn triangle_fan(self) -> Self { self.primitive_topology(PrimitiveTopology::TriangleFan) } - + /// Sets the topology of the primitives to a list of lines with adjacency information. /// /// > **Note**: This is equivalent to @@ -279,7 +482,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn line_list_with_adjacency(self) -> Self { self.primitive_topology(PrimitiveTopology::LineListWithAdjacency) } - + /// Sets the topology of the primitives to a line strip with adjacency information. /// /// > **Note**: This is equivalent to @@ -288,7 +491,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn line_strip_with_adjacency(self) -> Self { self.primitive_topology(PrimitiveTopology::LineStripWithAdjacency) } - + /// Sets the topology of the primitives to a list of triangles with adjacency information. /// /// > **Note**: This is equivalent to @@ -297,7 +500,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn triangle_list_with_adjacency(self) -> Self { self.primitive_topology(PrimitiveTopology::TriangleListWithAdjacency) } - + /// Sets the topology of the primitives to a triangle strip with adjacency information` /// /// > **Note**: This is equivalent to @@ -306,7 +509,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn triangle_strip_with_adjacency(self) -> Self { self.primitive_topology(PrimitiveTopology::TriangleStripWithAdjacency) } - + /// Sets the topology of the primitives to a list of patches. Can only be used and must be used /// with a tessellation shader. /// @@ -333,9 +536,9 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, vertex_shader: self.vertex_shader, input_assembly: self.input_assembly, tessellation: Some(GraphicsPipelineParamsTess { - tessellation_control_shader: tessellation_control_shader, - tessellation_evaluation_shader: tessellation_evaluation_shader, - }), + tessellation_control_shader: tessellation_control_shader, + tessellation_evaluation_shader: tessellation_evaluation_shader, + }), geometry_shader: self.geometry_shader, viewport: self.viewport, raster: self.raster, @@ -357,11 +560,32 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, /// Sets the geometry shader to use. // TODO: correct specialization constants #[inline] - pub fn geometry_shader(self, shader: GeometryShaderEntryPoint<'a, (), Gi2, Go2, Gl2>, + pub fn geometry_shader(self, + shader: GeometryShaderEntryPoint<'a, (), Gi2, Go2, Gl2>, specialization_constants: ()) - -> GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, - Tcl, Tes, Tei, Teo, Tel, (), Gi2, Go2, Gl2, Fs, Fi, Fo, Fl, Rp> - { + -> GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + (), + Gi2, + Go2, + Gl2, + Fs, + Fi, + Fo, + Fl, + Rp> { GraphicsPipelineBuilder { vertex_input: self.vertex_input, vertex_shader: self.vertex_shader, @@ -409,9 +633,8 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn viewports_dynamic_scissors_fixed(mut self, scissors: I) -> Self where I: IntoIterator { - self.viewport = Some(ViewportsState::DynamicViewports { - scissors: scissors.into_iter().collect() - }); + self.viewport = + Some(ViewportsState::DynamicViewports { scissors: scissors.into_iter().collect() }); self } @@ -420,8 +643,8 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, #[inline] pub fn viewports_dynamic_scissors_irrelevant(mut self, num: u32) -> Self { self.viewport = Some(ViewportsState::DynamicViewports { - scissors: (0 .. num).map(|_| Scissor::irrelevant()).collect() - }); + scissors: (0 .. num).map(|_| Scissor::irrelevant()).collect(), + }); self } @@ -431,9 +654,8 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, pub fn viewports_fixed_scissors_dynamic(mut self, viewports: I) -> Self where I: IntoIterator { - self.viewport = Some(ViewportsState::DynamicScissors { - viewports: viewports.into_iter().collect() - }); + self.viewport = + Some(ViewportsState::DynamicScissors { viewports: viewports.into_iter().collect() }); self } @@ -441,9 +663,7 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, /// drawing. #[inline] pub fn viewports_scissors_dynamic(mut self, num: u32) -> Self { - self.viewport = Some(ViewportsState::Dynamic { - num: num - }); + self.viewport = Some(ViewportsState::Dynamic { num: num }); self } @@ -562,11 +782,32 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, /// The fragment shader is run once for each pixel that is covered by each primitive. // TODO: correct specialization constants #[inline] - pub fn fragment_shader(self, shader: FragmentShaderEntryPoint<'a, (), Fi2, Fo2, Fl2>, + pub fn fragment_shader(self, + shader: FragmentShaderEntryPoint<'a, (), Fi2, Fo2, Fl2>, specialization_constants: ()) - -> GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, - Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, (), Fi2, Fo2, Fl2, Rp> - { + -> GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + (), + Fi2, + Fo2, + Fl2, + Rp> { GraphicsPipelineBuilder { vertex_input: self.vertex_input, vertex_shader: self.vertex_shader, @@ -680,9 +921,29 @@ impl<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gs, Gi, /// Sets the render pass subpass to use. #[inline] pub fn render_pass(self, subpass: Subpass) - -> GraphicsPipelineBuilder<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, - Tcl, Tes, Tei, Teo, Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp2> - { + -> GraphicsPipelineBuilder<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp2> { GraphicsPipelineBuilder { vertex_input: self.vertex_input, vertex_shader: self.vertex_shader, diff --git a/vulkano/src/pipeline/graphics_pipeline/mod.rs b/vulkano/src/pipeline/graphics_pipeline/mod.rs index 76fc4ad5..b042ec20 100644 --- a/vulkano/src/pipeline/graphics_pipeline/mod.rs +++ b/vulkano/src/pipeline/graphics_pipeline/mod.rs @@ -11,6 +11,7 @@ // to avoid duplicating code, so we hide the warnings for now #![allow(deprecated)] +use smallvec::SmallVec; use std::error; use std::fmt; use std::marker::PhantomData; @@ -18,45 +19,44 @@ use std::mem; use std::ptr; use std::sync::Arc; use std::u32; -use smallvec::SmallVec; +use Error; +use OomError; +use SafeDeref; +use VulkanObject; use buffer::BufferAccess; -use device::Device; -use device::DeviceOwned; +use check_errors; use descriptor::PipelineLayoutAbstract; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor_set::UnsafeDescriptorSetLayout; +use descriptor::pipeline_layout::EmptyPipelineDesc; use descriptor::pipeline_layout::PipelineLayout; use descriptor::pipeline_layout::PipelineLayoutDesc; use descriptor::pipeline_layout::PipelineLayoutDescNames; -use descriptor::pipeline_layout::PipelineLayoutDescUnion; use descriptor::pipeline_layout::PipelineLayoutDescPcRange; -use descriptor::pipeline_layout::PipelineLayoutSuperset; +use descriptor::pipeline_layout::PipelineLayoutDescUnion; use descriptor::pipeline_layout::PipelineLayoutNotSupersetError; +use descriptor::pipeline_layout::PipelineLayoutSuperset; use descriptor::pipeline_layout::PipelineLayoutSys; -use descriptor::pipeline_layout::EmptyPipelineDesc; +use device::Device; +use device::DeviceOwned; use format::ClearValue; use framebuffer::LayoutAttachmentDescription; -use framebuffer::LayoutPassDescription; use framebuffer::LayoutPassDependencyDescription; +use framebuffer::LayoutPassDescription; use framebuffer::RenderPassAbstract; use framebuffer::RenderPassDesc; use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassSubpassInterface; use framebuffer::RenderPassSys; use framebuffer::Subpass; -use Error; -use OomError; -use SafeDeref; -use VulkanObject; -use check_errors; use vk; -use pipeline::blend::Blend; use pipeline::blend::AttachmentsBlend; +use pipeline::blend::Blend; use pipeline::depth_stencil::Compare; -use pipeline::depth_stencil::DepthStencil; use pipeline::depth_stencil::DepthBounds; +use pipeline::depth_stencil::DepthStencil; use pipeline::input_assembly::InputAssembly; use pipeline::input_assembly::PrimitiveTopology; use pipeline::multisample::Multisample; @@ -64,18 +64,18 @@ use pipeline::raster::DepthBiasControl; use pipeline::raster::PolygonMode; use pipeline::raster::Rasterization; use pipeline::shader::EmptyShaderInterfaceDef; +use pipeline::shader::FragmentShaderEntryPoint; +use pipeline::shader::GeometryShaderEntryPoint; use pipeline::shader::ShaderInterfaceDef; use pipeline::shader::ShaderInterfaceDefMatch; use pipeline::shader::ShaderInterfaceMismatchError; -use pipeline::shader::VertexShaderEntryPoint; use pipeline::shader::TessControlShaderEntryPoint; use pipeline::shader::TessEvaluationShaderEntryPoint; -use pipeline::shader::GeometryShaderEntryPoint; -use pipeline::shader::FragmentShaderEntryPoint; +use pipeline::shader::VertexShaderEntryPoint; +use pipeline::vertex::IncompatibleVertexDefinitionError; use pipeline::vertex::SingleBufferDefinition; use pipeline::vertex::VertexDefinition; use pipeline::vertex::VertexSource; -use pipeline::vertex::IncompatibleVertexDefinitionError; use pipeline::viewport::ViewportsState; pub use self::builder::GraphicsPipelineBuilder; @@ -86,8 +86,29 @@ mod builder; /// Description of a `GraphicsPipeline`. #[deprecated = "Use the GraphicsPipelineBuilder instead"] -pub struct GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, - Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp> +pub struct GraphicsPipelineParams<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gs, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp> { /// Describes the layout of the vertex input. /// @@ -106,7 +127,8 @@ pub struct GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, /// Parameters of the tessellation stage. `None` if you don't want to use tessellation. /// If you use tessellation, you must enable the `tessellation_shader` feature on the device. - pub tessellation: Option>, + pub tessellation: + Option>, /// The entry point of the geometry shader. `None` if you don't want a geometry shader. /// If you use a geometry shader, you must enable the `geometry_shader` feature on the device. @@ -181,14 +203,30 @@ struct Inner { impl GraphicsPipeline<(), (), ()> { /// Starts the building process of a graphics pipeline. Returns a builder object that you can /// fill with the various parameters. - pub fn start<'a>() -> GraphicsPipelineBuilder<'a, SingleBufferDefinition<()>, (), (), (), (), - (), EmptyShaderInterfaceDef, - EmptyShaderInterfaceDef, EmptyPipelineDesc, (), - EmptyShaderInterfaceDef, EmptyShaderInterfaceDef, - EmptyPipelineDesc, (), EmptyShaderInterfaceDef, - EmptyShaderInterfaceDef, EmptyPipelineDesc, (), - EmptyShaderInterfaceDef, EmptyShaderInterfaceDef, - EmptyPipelineDesc, ()> + pub fn start<'a>() + -> GraphicsPipelineBuilder<'a, + SingleBufferDefinition<()>, + (), + (), + (), + (), + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + (), + EmptyShaderInterfaceDef, + EmptyShaderInterfaceDef, + EmptyPipelineDesc, + ()> { GraphicsPipelineBuilder::new() } @@ -220,17 +258,42 @@ impl GraphicsPipeline Vo: ShaderInterfaceDef, Rp: RenderPassSubpassInterface, { - if let Err(err) = params.fragment_shader.input().matches(params.vertex_shader.output()) { - return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); + if let Err(err) = params + .fragment_shader + .input() + .matches(params.vertex_shader.output()) + { + return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); } - let pl = params.vertex_shader.layout().clone() - .union(params.fragment_shader.layout().clone()) - .build(device.clone()).unwrap(); // TODO: error + let pl = params + .vertex_shader + .layout() + .clone() + .union(params.fragment_shader.layout().clone()) + .build(device.clone()) + .unwrap(); // TODO: error - GraphicsPipeline::new_inner::<_, _, _, _, (), (), (), EmptyPipelineDesc, (), (), (), - EmptyPipelineDesc, (), (), (), EmptyPipelineDesc, _, _, _, _> - (device, params, pl) + GraphicsPipeline::new_inner::<_, + _, + _, + _, + (), + (), + (), + EmptyPipelineDesc, + (), + (), + (), + EmptyPipelineDesc, + (), + (), + (), + EmptyPipelineDesc, + _, + _, + _, + _>(device, params, pl) } /// Builds a new graphics pipeline object with a geometry shader. @@ -260,23 +323,34 @@ impl GraphicsPipeline Rp: RenderPassSubpassInterface, { if let Some(ref geometry_shader) = params.geometry_shader { - if let Err(err) = geometry_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = geometry_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexGeometryStagesMismatch(err)); }; - if let Err(err) = params.fragment_shader.input().matches(geometry_shader.output()) { - return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err)); + if let Err(err) = params + .fragment_shader + .input() + .matches(geometry_shader.output()) + { + return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err)); } } else { - if let Err(err) = params.fragment_shader.input().matches(params.vertex_shader.output()) { - return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); + if let Err(err) = params + .fragment_shader + .input() + .matches(params.vertex_shader.output()) + { + return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); } } let pl = params.vertex_shader.layout().clone() .union(params.fragment_shader.layout().clone()) .union(params.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap() - .build(device.clone()).unwrap(); // TODO: error + .build(device.clone()).unwrap(); // TODO: error GraphicsPipeline::new_inner(device.clone(), params, pl) } @@ -313,19 +387,33 @@ impl GraphicsPipeline Rp: RenderPassAbstract + RenderPassSubpassInterface, { if let Some(ref tess) = params.tessellation { - if let Err(err) = tess.tessellation_control_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = tess.tessellation_control_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err)); } - if let Err(err) = tess.tessellation_evaluation_shader.input().matches(tess.tessellation_control_shader.output()) { + if let Err(err) = tess.tessellation_evaluation_shader + .input() + .matches(tess.tessellation_control_shader.output()) + { return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err)); } - if let Err(err) = params.fragment_shader.input().matches(tess.tessellation_evaluation_shader.output()) { + if let Err(err) = params + .fragment_shader + .input() + .matches(tess.tessellation_evaluation_shader.output()) + { return Err(GraphicsPipelineCreationError::TessEvalFragmentStagesMismatch(err)); } } else { - if let Err(err) = params.fragment_shader.input().matches(params.vertex_shader.output()) { - return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); + if let Err(err) = params + .fragment_shader + .input() + .matches(params.vertex_shader.output()) + { + return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); } } @@ -333,7 +421,7 @@ impl GraphicsPipeline .union(params.fragment_shader.layout().clone()) .union(params.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap() .union(params.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap() - .build(device.clone()).unwrap(); // TODO: error + .build(device.clone()).unwrap(); // TODO: error GraphicsPipeline::new_inner(device, params, pl) } @@ -349,19 +437,59 @@ impl GraphicsPipeline // TODO: replace Box with a PipelineUnion struct without template params #[inline] #[deprecated = "Use the GraphicsPipelineBuilder instead"] - pub fn with_tessellation_and_geometry<'a, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gsp, Gi, - Go, Gl, Fs, Fi, Fo, Fl> - (device: Arc, - params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, - Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, Fi, - Fo, Fl, Rp>) - -> Result, Rp>, GraphicsPipelineCreationError> + pub fn with_tessellation_and_geometry<'a, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gsp, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl>( + device: Arc, + params: GraphicsPipelineParams<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gsp, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp>) + -> Result, Rp>, + GraphicsPipelineCreationError> where Vdef: VertexDefinition, - Vl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Fl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Tcl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Tel: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required - Gl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Vl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Fl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Tcl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Tel: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required + Gl: PipelineLayoutDescNames + Clone + 'static + Send + Sync, // TODO: Clone + 'static + Send + Sync shouldn't be required Tci: ShaderInterfaceDefMatch, Tei: ShaderInterfaceDefMatch, Gi: ShaderInterfaceDefMatch + ShaderInterfaceDefMatch, @@ -369,21 +497,31 @@ impl GraphicsPipeline Tco: ShaderInterfaceDef, Teo: ShaderInterfaceDef, Go: ShaderInterfaceDef, - Fi: ShaderInterfaceDefMatch + ShaderInterfaceDefMatch + ShaderInterfaceDefMatch, + Fi: ShaderInterfaceDefMatch + + ShaderInterfaceDefMatch + + ShaderInterfaceDefMatch, Fo: ShaderInterfaceDef, - Rp: RenderPassAbstract + RenderPassSubpassInterface, + Rp: RenderPassAbstract + RenderPassSubpassInterface { let pl; if let Some(ref tess) = params.tessellation { if let Some(ref gs) = params.geometry_shader { - if let Err(err) = tess.tessellation_control_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = tess.tessellation_control_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err)); } - if let Err(err) = tess.tessellation_evaluation_shader.input().matches(tess.tessellation_control_shader.output()) { + if let Err(err) = tess.tessellation_evaluation_shader + .input() + .matches(tess.tessellation_control_shader.output()) + { return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err)); } - if let Err(err) = gs.input().matches(tess.tessellation_evaluation_shader.output()) { + if let Err(err) = gs.input() + .matches(tess.tessellation_evaluation_shader.output()) + { return Err(GraphicsPipelineCreationError::TessEvalGeometryStagesMismatch(err)); } if let Err(err) = params.fragment_shader.input().matches(gs.output()) { @@ -395,16 +533,26 @@ impl GraphicsPipeline .union(params.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap() .union(params.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap() .union(params.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap() - .build(device.clone()).unwrap()) as Box<_>; // TODO: error + .build(device.clone()).unwrap()) as Box<_>; // TODO: error } else { - if let Err(err) = tess.tessellation_control_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = tess.tessellation_control_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err)); } - if let Err(err) = tess.tessellation_evaluation_shader.input().matches(tess.tessellation_control_shader.output()) { + if let Err(err) = tess.tessellation_evaluation_shader + .input() + .matches(tess.tessellation_control_shader.output()) + { return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err)); } - if let Err(err) = params.fragment_shader.input().matches(tess.tessellation_evaluation_shader.output()) { + if let Err(err) = params + .fragment_shader + .input() + .matches(tess.tessellation_evaluation_shader.output()) + { return Err(GraphicsPipelineCreationError::TessEvalFragmentStagesMismatch(err)); } @@ -412,31 +560,46 @@ impl GraphicsPipeline .union(params.fragment_shader.layout().clone()) .union(params.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap() .union(params.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap() - .build(device.clone()).unwrap()) as Box<_>; // TODO: error + .build(device.clone()).unwrap()) as Box<_>; // TODO: error } } else { if let Some(ref geometry_shader) = params.geometry_shader { - if let Err(err) = geometry_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = geometry_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexGeometryStagesMismatch(err)); } - if let Err(err) = params.fragment_shader.input().matches(geometry_shader.output()) { + if let Err(err) = params + .fragment_shader + .input() + .matches(geometry_shader.output()) + { return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err)); } pl = Box::new(params.vertex_shader.layout().clone() .union(params.fragment_shader.layout().clone()) .union(params.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap() - .build(device.clone()).unwrap()) as Box<_>; // TODO: error + .build(device.clone()).unwrap()) as Box<_>; // TODO: error } else { - if let Err(err) = params.fragment_shader.input().matches(params.vertex_shader.output()) { + if let Err(err) = params + .fragment_shader + .input() + .matches(params.vertex_shader.output()) + { return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); } - pl = Box::new(params.vertex_shader.layout().clone() - .union(params.fragment_shader.layout().clone()) - .build(device.clone()).unwrap()) as Box<_>; // TODO: error + pl = Box::new(params + .vertex_shader + .layout() + .clone() + .union(params.fragment_shader.layout().clone()) + .build(device.clone()) + .unwrap()) as Box<_>; // TODO: error } } @@ -447,13 +610,53 @@ impl GraphicsPipeline impl GraphicsPipeline where L: PipelineLayoutAbstract { - fn new_inner<'a, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, - Fi, Fo, Fl> - (device: Arc, - params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, - Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp>, - pipeline_layout: L) - -> Result, GraphicsPipelineCreationError> + fn new_inner<'a, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gsp, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl>( + device: Arc, + params: GraphicsPipelineParams<'a, + Vdef, + Vsp, + Vi, + Vo, + Vl, + Tcs, + Tci, + Tco, + Tcl, + Tes, + Tei, + Teo, + Tel, + Gsp, + Gi, + Go, + Gl, + Fs, + Fi, + Fo, + Fl, + Rp>, + pipeline_layout: L) + -> Result, GraphicsPipelineCreationError> where Vdef: VertexDefinition, Fo: ShaderInterfaceDef, Vl: PipelineLayoutDescNames, @@ -461,7 +664,7 @@ impl GraphicsPipeline Gl: PipelineLayoutDescNames, Tcl: PipelineLayoutDescNames, Tel: PipelineLayoutDescNames, - Rp: RenderPassAbstract + RenderPassDesc + RenderPassSubpassInterface, + Rp: RenderPassAbstract + RenderPassDesc + RenderPassSubpassInterface { let vk = device.pointers(); @@ -472,14 +675,14 @@ impl GraphicsPipeline PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, params.fragment_shader.layout())?; if let Some(ref geometry_shader) = params.geometry_shader { - PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, - geometry_shader.layout())?; + PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, geometry_shader.layout())?; } if let Some(ref tess) = params.tessellation { PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, tess.tessellation_control_shader.layout())?; PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, - tess.tessellation_evaluation_shader.layout())?; + tess.tessellation_evaluation_shader + .layout())?; } // Check that the subpass can accept the output of the fragment shader. @@ -498,24 +701,24 @@ impl GraphicsPipeline let mut stages = SmallVec::<[_; 5]>::new(); stages.push(vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_VERTEX_BIT, - module: params.vertex_shader.module().internal_object(), - pName: params.vertex_shader.name().as_ptr(), - pSpecializationInfo: ptr::null(), // TODO: - }); + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_VERTEX_BIT, + module: params.vertex_shader.module().internal_object(), + pName: params.vertex_shader.name().as_ptr(), + pSpecializationInfo: ptr::null(), // TODO: + }); stages.push(vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_FRAGMENT_BIT, - module: params.fragment_shader.module().internal_object(), - pName: params.fragment_shader.name().as_ptr(), - pSpecializationInfo: ptr::null(), // TODO: - }); + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_FRAGMENT_BIT, + module: params.fragment_shader.module().internal_object(), + pName: params.fragment_shader.name().as_ptr(), + pSpecializationInfo: ptr::null(), // TODO: + }); if let Some(ref gs) = params.geometry_shader { if !device.enabled_features().geometry_shader { @@ -523,14 +726,14 @@ impl GraphicsPipeline } stages.push(vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_GEOMETRY_BIT, - module: gs.module().internal_object(), - pName: gs.name().as_ptr(), - pSpecializationInfo: ptr::null(), // TODO: - }); + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_GEOMETRY_BIT, + module: gs.module().internal_object(), + pName: gs.name().as_ptr(), + pSpecializationInfo: ptr::null(), // TODO: + }); } if let Some(ref tess) = params.tessellation { @@ -541,24 +744,26 @@ impl GraphicsPipeline } stages.push(vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT, - module: tess.tessellation_control_shader.module().internal_object(), - pName: tess.tessellation_control_shader.name().as_ptr(), - pSpecializationInfo: ptr::null(), // TODO: - }); + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT, + module: tess.tessellation_control_shader.module().internal_object(), + pName: tess.tessellation_control_shader.name().as_ptr(), + pSpecializationInfo: ptr::null(), // TODO: + }); stages.push(vk::PipelineShaderStageCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - stage: vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT, - module: tess.tessellation_evaluation_shader.module().internal_object(), - pName: tess.tessellation_evaluation_shader.name().as_ptr(), - pSpecializationInfo: ptr::null(), // TODO: - }); + sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + stage: vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT, + module: tess.tessellation_evaluation_shader + .module() + .internal_object(), + pName: tess.tessellation_evaluation_shader.name().as_ptr(), + pSpecializationInfo: ptr::null(), // TODO: + }); } stages @@ -566,11 +771,19 @@ impl GraphicsPipeline // Vertex bindings. let (binding_descriptions, attribute_descriptions) = { - let (buffers_iter, attribs_iter) = try!(params.vertex_input.definition(params.vertex_shader.input_definition())); + let (buffers_iter, attribs_iter) = + params + .vertex_input + .definition(params.vertex_shader.input_definition())?; let mut binding_descriptions = SmallVec::<[_; 8]>::new(); for (num, stride, rate) in buffers_iter { - if stride > device.physical_device().limits().max_vertex_input_binding_stride() as usize { + if stride > + device + .physical_device() + .limits() + .max_vertex_input_binding_stride() as usize + { return Err(GraphicsPipelineCreationError::MaxVertexInputBindingStrideExceeded { binding: num as usize, max: device.physical_device().limits().max_vertex_input_binding_stride() as usize, @@ -579,58 +792,80 @@ impl GraphicsPipeline } binding_descriptions.push(vk::VertexInputBindingDescription { - binding: num as u32, - stride: stride as u32, - inputRate: rate as u32, - }); + binding: num as u32, + stride: stride as u32, + inputRate: rate as u32, + }); } let mut attribute_descriptions = SmallVec::<[_; 8]>::new(); for (loc, binding, info) in attribs_iter { // TODO: check attribute format support - if info.offset > device.physical_device().limits().max_vertex_input_attribute_offset() as usize { + if info.offset > + device + .physical_device() + .limits() + .max_vertex_input_attribute_offset() as usize + { return Err(GraphicsPipelineCreationError::MaxVertexInputAttributeOffsetExceeded { max: device.physical_device().limits().max_vertex_input_attribute_offset() as usize, obtained: info.offset, }); } - debug_assert!(binding_descriptions.iter().find(|b| b.binding == binding).is_some()); + debug_assert!(binding_descriptions + .iter() + .find(|b| b.binding == binding) + .is_some()); attribute_descriptions.push(vk::VertexInputAttributeDescription { - location: loc as u32, - binding: binding as u32, - format: info.format as u32, - offset: info.offset as u32, - }); + location: loc as u32, + binding: binding as u32, + format: info.format as u32, + offset: info.offset as u32, + }); } (binding_descriptions, attribute_descriptions) }; - if binding_descriptions.len() > device.physical_device().limits() - .max_vertex_input_bindings() as usize + if binding_descriptions.len() > + device + .physical_device() + .limits() + .max_vertex_input_bindings() as usize { return Err(GraphicsPipelineCreationError::MaxVertexInputBindingsExceeded { - max: device.physical_device().limits().max_vertex_input_bindings() as usize, - obtained: binding_descriptions.len(), - }); + max: device + .physical_device() + .limits() + .max_vertex_input_bindings() as + usize, + obtained: binding_descriptions.len(), + }); } - if attribute_descriptions.len() > device.physical_device().limits() - .max_vertex_input_attributes() as usize + if attribute_descriptions.len() > + device + .physical_device() + .limits() + .max_vertex_input_attributes() as usize { return Err(GraphicsPipelineCreationError::MaxVertexInputAttributesExceeded { - max: device.physical_device().limits().max_vertex_input_attributes() as usize, - obtained: attribute_descriptions.len(), - }); + max: device + .physical_device() + .limits() + .max_vertex_input_attributes() as + usize, + obtained: attribute_descriptions.len(), + }); } let vertex_input_state = vk::PipelineVertexInputStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved vertexBindingDescriptionCount: binding_descriptions.len() as u32, pVertexBindingDescriptions: binding_descriptions.as_ptr(), vertexAttributeDescriptionCount: attribute_descriptions.len() as u32, @@ -638,11 +873,11 @@ impl GraphicsPipeline }; if params.input_assembly.primitive_restart_enable && - !params.input_assembly.topology.supports_primitive_restart() + !params.input_assembly.topology.supports_primitive_restart() { return Err(GraphicsPipelineCreationError::PrimitiveDoesntSupportPrimitiveRestart { - primitive: params.input_assembly.topology - }); + primitive: params.input_assembly.topology, + }); } // TODO: should check from the tess eval shader instead of the input assembly @@ -655,7 +890,7 @@ impl GraphicsPipeline let input_assembly = vk::PipelineInputAssemblyStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved topology: params.input_assembly.topology.into(), primitiveRestartEnable: if params.input_assembly.primitive_restart_enable { vk::TRUE @@ -669,18 +904,21 @@ impl GraphicsPipeline if params.tessellation.is_none() { return Err(GraphicsPipelineCreationError::InvalidPrimitiveTopology); } - if vertices_per_patch > device.physical_device().limits() - .max_tessellation_patch_size() + if vertices_per_patch > + device + .physical_device() + .limits() + .max_tessellation_patch_size() { return Err(GraphicsPipelineCreationError::MaxTessellationPatchSizeExceeded); } Some(vk::PipelineTessellationStateCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved, - patchControlPoints: vertices_per_patch, - }) + sType: vk::STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved, + patchControlPoints: vertices_per_patch, + }) }, _ => { if params.tessellation.is_some() { @@ -688,26 +926,32 @@ impl GraphicsPipeline } None - } + }, }; let (vp_vp, vp_sc, vp_num) = match params.viewport { - ViewportsState::Fixed { ref data } => ( - data.iter().map(|e| e.0.clone().into()).collect::>(), - data.iter().map(|e| e.1.clone().into()).collect::>(), - data.len() as u32 - ), + ViewportsState::Fixed { ref data } => (data.iter() + .map(|e| e.0.clone().into()) + .collect::>(), + data.iter() + .map(|e| e.1.clone().into()) + .collect::>(), + data.len() as u32), ViewportsState::DynamicViewports { ref scissors } => { let num = scissors.len() as u32; - let scissors = scissors.iter().map(|e| e.clone().into()) - .collect::>(); + let scissors = scissors + .iter() + .map(|e| e.clone().into()) + .collect::>(); dynamic_states.push(vk::DYNAMIC_STATE_VIEWPORT); (SmallVec::new(), scissors, num) }, ViewportsState::DynamicScissors { ref viewports } => { let num = viewports.len() as u32; - let viewports = viewports.iter().map(|e| e.clone().into()) - .collect::>(); + let viewports = viewports + .iter() + .map(|e| e.clone().into()) + .collect::>(); dynamic_states.push(vk::DYNAMIC_STATE_SCISSOR); (viewports, SmallVec::new(), num) }, @@ -724,22 +968,22 @@ impl GraphicsPipeline if vp_num > device.physical_device().limits().max_viewports() { return Err(GraphicsPipelineCreationError::MaxViewportsExceeded { - obtained: vp_num, - max: device.physical_device().limits().max_viewports(), - }); + obtained: vp_num, + max: device.physical_device().limits().max_viewports(), + }); } for vp in vp_vp.iter() { if vp.width > device.physical_device().limits().max_viewport_dimensions()[0] as f32 || - vp.height > device.physical_device().limits().max_viewport_dimensions()[1] as f32 + vp.height > device.physical_device().limits().max_viewport_dimensions()[1] as f32 { return Err(GraphicsPipelineCreationError::MaxViewportDimensionsExceeded); } if vp.x < device.physical_device().limits().viewport_bounds_range()[0] || - vp.x + vp.width > device.physical_device().limits().viewport_bounds_range()[1] || - vp.y < device.physical_device().limits().viewport_bounds_range()[0] || - vp.y + vp.height > device.physical_device().limits().viewport_bounds_range()[1] + vp.x + vp.width > device.physical_device().limits().viewport_bounds_range()[1] || + vp.y < device.physical_device().limits().viewport_bounds_range()[0] || + vp.y + vp.height > device.physical_device().limits().viewport_bounds_range()[1] { return Err(GraphicsPipelineCreationError::ViewportBoundsExceeded); } @@ -748,11 +992,19 @@ impl GraphicsPipeline let viewport_info = vk::PipelineViewportStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved viewportCount: vp_num, - pViewports: if vp_vp.is_empty() { ptr::null() } else { vp_vp.as_ptr() }, // validation layer crashes if you just pass the pointer + pViewports: if vp_vp.is_empty() { + ptr::null() + } else { + vp_vp.as_ptr() + }, // validation layer crashes if you just pass the pointer scissorCount: vp_num, - pScissors: if vp_sc.is_empty() { ptr::null() } else { vp_sc.as_ptr() }, // validation layer crashes if you just pass the pointer + pScissors: if vp_sc.is_empty() { + ptr::null() + } else { + vp_sc.as_ptr() + }, // validation layer crashes if you just pass the pointer }; if let Some(line_width) = params.raster.line_width { @@ -785,7 +1037,7 @@ impl GraphicsPipeline } if params.raster.polygon_mode != PolygonMode::Fill && - !device.enabled_features().fill_mode_non_solid + !device.enabled_features().fill_mode_non_solid { return Err(GraphicsPipelineCreationError::FillModeNonSolidFeatureNotEnabled); } @@ -793,9 +1045,17 @@ impl GraphicsPipeline let rasterization = vk::PipelineRasterizationStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved - depthClampEnable: if params.raster.depth_clamp { vk::TRUE } else { vk::FALSE }, - rasterizerDiscardEnable: if params.raster.rasterizer_discard { vk::TRUE } else { vk::FALSE }, + flags: 0, // reserved + depthClampEnable: if params.raster.depth_clamp { + vk::TRUE + } else { + vk::FALSE + }, + rasterizerDiscardEnable: if params.raster.rasterizer_discard { + vk::TRUE + } else { + vk::FALSE + }, polygonMode: params.raster.polygon_mode as u32, cullMode: params.raster.cull_mode as u32, frontFace: params.raster.front_face as u32, @@ -808,17 +1068,31 @@ impl GraphicsPipeline assert!(params.multisample.rasterization_samples >= 1); // FIXME: check that rasterization_samples is equal to what's in the renderpass - if let Some(s) = params.multisample.sample_shading { assert!(s >= 0.0 && s <= 1.0); } + if let Some(s) = params.multisample.sample_shading { + assert!(s >= 0.0 && s <= 1.0); + } let multisample = vk::PipelineMultisampleStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved rasterizationSamples: params.multisample.rasterization_samples, - sampleShadingEnable: if params.multisample.sample_shading.is_some() { vk::TRUE } else { vk::FALSE }, + sampleShadingEnable: if params.multisample.sample_shading.is_some() { + vk::TRUE + } else { + vk::FALSE + }, minSampleShading: params.multisample.sample_shading.unwrap_or(1.0), - pSampleMask: ptr::null(), //params.multisample.sample_mask.as_ptr(), // FIXME: - alphaToCoverageEnable: if params.multisample.alpha_to_coverage { vk::TRUE } else { vk::FALSE }, - alphaToOneEnable: if params.multisample.alpha_to_one { vk::TRUE } else { vk::FALSE }, + pSampleMask: ptr::null(), //params.multisample.sample_mask.as_ptr(), // FIXME: + alphaToCoverageEnable: if params.multisample.alpha_to_coverage { + vk::TRUE + } else { + vk::FALSE + }, + alphaToOneEnable: if params.multisample.alpha_to_one { + vk::TRUE + } else { + vk::FALSE + }, }; let depth_stencil = { @@ -843,33 +1117,30 @@ impl GraphicsPipeline }; match (params.depth_stencil.stencil_front.compare_mask, - params.depth_stencil.stencil_back.compare_mask) - { + params.depth_stencil.stencil_back.compare_mask) { (Some(_), Some(_)) => (), (None, None) => { dynamic_states.push(vk::DYNAMIC_STATE_STENCIL_COMPARE_MASK); }, - _ => return Err(GraphicsPipelineCreationError::WrongStencilState) + _ => return Err(GraphicsPipelineCreationError::WrongStencilState), }; match (params.depth_stencil.stencil_front.write_mask, - params.depth_stencil.stencil_back.write_mask) - { + params.depth_stencil.stencil_back.write_mask) { (Some(_), Some(_)) => (), (None, None) => { dynamic_states.push(vk::DYNAMIC_STATE_STENCIL_WRITE_MASK); }, - _ => return Err(GraphicsPipelineCreationError::WrongStencilState) + _ => return Err(GraphicsPipelineCreationError::WrongStencilState), }; match (params.depth_stencil.stencil_front.reference, - params.depth_stencil.stencil_back.reference) - { + params.depth_stencil.stencil_back.reference) { (Some(_), Some(_)) => (), (None, None) => { dynamic_states.push(vk::DYNAMIC_STATE_STENCIL_REFERENCE); }, - _ => return Err(GraphicsPipelineCreationError::WrongStencilState) + _ => return Err(GraphicsPipelineCreationError::WrongStencilState), }; if params.depth_stencil.depth_write && !params.render_pass.has_writable_depth() { @@ -877,13 +1148,13 @@ impl GraphicsPipeline } if params.depth_stencil.depth_compare != Compare::Always && - !params.render_pass.has_depth() + !params.render_pass.has_depth() { return Err(GraphicsPipelineCreationError::NoDepthAttachment); } if (!params.depth_stencil.stencil_front.always_keep() || - !params.depth_stencil.stencil_back.always_keep()) && + !params.depth_stencil.stencil_back.always_keep()) && !params.render_pass.has_stencil() { return Err(GraphicsPipelineCreationError::NoStencilAttachment); @@ -894,24 +1165,43 @@ impl GraphicsPipeline vk::PipelineDepthStencilStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved depthTestEnable: if !params.depth_stencil.depth_write && - params.depth_stencil.depth_compare == Compare::Always - { vk::FALSE } else { vk::TRUE }, - depthWriteEnable: if params.depth_stencil.depth_write { vk::TRUE } - else { vk::FALSE }, + params.depth_stencil.depth_compare == Compare::Always + { + vk::FALSE + } else { + vk::TRUE + }, + depthWriteEnable: if params.depth_stencil.depth_write { + vk::TRUE + } else { + vk::FALSE + }, depthCompareOp: params.depth_stencil.depth_compare as u32, depthBoundsTestEnable: db.0, stencilTestEnable: if params.depth_stencil.stencil_front.always_keep() && - params.depth_stencil.stencil_back.always_keep() - { vk::FALSE } else { vk::TRUE }, + params.depth_stencil.stencil_back.always_keep() + { + vk::FALSE + } else { + vk::TRUE + }, front: vk::StencilOpState { failOp: params.depth_stencil.stencil_front.fail_op as u32, passOp: params.depth_stencil.stencil_front.pass_op as u32, depthFailOp: params.depth_stencil.stencil_front.depth_fail_op as u32, compareOp: params.depth_stencil.stencil_front.compare as u32, - compareMask: params.depth_stencil.stencil_front.compare_mask.unwrap_or(u32::MAX), - writeMask: params.depth_stencil.stencil_front.write_mask.unwrap_or(u32::MAX), + compareMask: params + .depth_stencil + .stencil_front + .compare_mask + .unwrap_or(u32::MAX), + writeMask: params + .depth_stencil + .stencil_front + .write_mask + .unwrap_or(u32::MAX), reference: params.depth_stencil.stencil_front.reference.unwrap_or(0), }, back: vk::StencilOpState { @@ -919,9 +1209,17 @@ impl GraphicsPipeline passOp: params.depth_stencil.stencil_back.pass_op as u32, depthFailOp: params.depth_stencil.stencil_back.depth_fail_op as u32, compareOp: params.depth_stencil.stencil_back.compare as u32, - compareMask: params.depth_stencil.stencil_back.compare_mask.unwrap_or(u32::MAX), - writeMask: params.depth_stencil.stencil_back.write_mask.unwrap_or(u32::MAX), - reference: params.depth_stencil.stencil_back.reference.unwrap_or(0) + compareMask: params + .depth_stencil + .stencil_back + .compare_mask + .unwrap_or(u32::MAX), + writeMask: params + .depth_stencil + .stencil_back + .write_mask + .unwrap_or(u32::MAX), + reference: params.depth_stencil.stencil_back.reference.unwrap_or(0), }, minDepthBounds: db.1, maxDepthBounds: db.2, @@ -952,7 +1250,7 @@ impl GraphicsPipeline let blend = vk::PipelineColorBlendStateCreateInfo { sType: vk::STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved logicOpEnable: if params.blend.logic_op.is_some() { if !device.enabled_features().logic_op { return Err(GraphicsPipelineCreationError::LogicOpFeatureNotEnabled); @@ -969,17 +1267,17 @@ impl GraphicsPipeline } else { dynamic_states.push(vk::DYNAMIC_STATE_BLEND_CONSTANTS); [0.0, 0.0, 0.0, 0.0] - } + }, }; let dynamic_states = if !dynamic_states.is_empty() { Some(vk::PipelineDynamicStateCreateInfo { - sType: vk::STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - pNext: ptr::null(), - flags: 0, // reserved - dynamicStateCount: dynamic_states.len() as u32, - pDynamicStates: dynamic_states.as_ptr(), - }) + sType: vk::STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + pNext: ptr::null(), + flags: 0, // reserved + dynamicStateCount: dynamic_states.len() as u32, + pDynamicStates: dynamic_states.as_ptr(), + }) } else { None }; @@ -988,59 +1286,71 @@ impl GraphicsPipeline let infos = vk::GraphicsPipelineCreateInfo { sType: vk::STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // TODO: some flags are available but none are critical + flags: 0, // TODO: some flags are available but none are critical stageCount: stages.len() as u32, pStages: stages.as_ptr(), pVertexInputState: &vertex_input_state, pInputAssemblyState: &input_assembly, - pTessellationState: tessellation.as_ref().map(|t| t as *const _) - .unwrap_or(ptr::null()), + pTessellationState: tessellation + .as_ref() + .map(|t| t as *const _) + .unwrap_or(ptr::null()), pViewportState: &viewport_info, pRasterizationState: &rasterization, pMultisampleState: &multisample, pDepthStencilState: &depth_stencil, pColorBlendState: &blend, - pDynamicState: dynamic_states.as_ref().map(|s| s as *const _) - .unwrap_or(ptr::null()), + pDynamicState: dynamic_states + .as_ref() + .map(|s| s as *const _) + .unwrap_or(ptr::null()), layout: PipelineLayoutAbstract::sys(&pipeline_layout).internal_object(), renderPass: params.render_pass.render_pass().inner().internal_object(), subpass: params.render_pass.index(), - basePipelineHandle: 0, // TODO: - basePipelineIndex: -1, // TODO: + basePipelineHandle: 0, // TODO: + basePipelineIndex: -1, // TODO: }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateGraphicsPipelines(device.internal_object(), 0, - 1, &infos, ptr::null(), &mut output))); + check_errors(vk.CreateGraphicsPipelines(device.internal_object(), + 0, + 1, + &infos, + ptr::null(), + &mut output))?; output }; let (render_pass, render_pass_subpass) = params.render_pass.into(); Ok(GraphicsPipeline { - inner: Inner { - device: device.clone(), - pipeline: pipeline, - }, - layout: pipeline_layout, + inner: Inner { + device: device.clone(), + pipeline: pipeline, + }, + layout: pipeline_layout, - vertex_definition: params.vertex_input, + vertex_definition: params.vertex_input, - render_pass: render_pass, - render_pass_subpass: render_pass_subpass, + render_pass: render_pass, + render_pass_subpass: render_pass_subpass, - dynamic_line_width: params.raster.line_width.is_none(), - dynamic_viewport: params.viewport.dynamic_viewports(), - dynamic_scissor: params.viewport.dynamic_scissors(), - dynamic_depth_bias: params.raster.depth_bias.is_dynamic(), - dynamic_depth_bounds: params.depth_stencil.depth_bounds_test.is_dynamic(), - dynamic_stencil_compare_mask: params.depth_stencil.stencil_back.compare_mask.is_none(), - dynamic_stencil_write_mask: params.depth_stencil.stencil_back.write_mask.is_none(), - dynamic_stencil_reference: params.depth_stencil.stencil_back.reference.is_none(), - dynamic_blend_constants: params.blend.blend_constants.is_none(), + dynamic_line_width: params.raster.line_width.is_none(), + dynamic_viewport: params.viewport.dynamic_viewports(), + dynamic_scissor: params.viewport.dynamic_scissors(), + dynamic_depth_bias: params.raster.depth_bias.is_dynamic(), + dynamic_depth_bounds: params.depth_stencil.depth_bounds_test.is_dynamic(), + dynamic_stencil_compare_mask: params + .depth_stencil + .stencil_back + .compare_mask + .is_none(), + dynamic_stencil_write_mask: params.depth_stencil.stencil_back.write_mask.is_none(), + dynamic_stencil_reference: params.depth_stencil.stencil_back.reference.is_none(), + dynamic_blend_constants: params.blend.blend_constants.is_none(), - num_viewports: params.viewport.num_viewports(), - }) + num_viewports: params.viewport.num_viewports(), + }) } } @@ -1148,7 +1458,9 @@ unsafe impl PipelineLayoutAbstract for GraphicsPipeline } } -unsafe impl PipelineLayoutDesc for GraphicsPipeline where L: PipelineLayoutDesc { +unsafe impl PipelineLayoutDesc for GraphicsPipeline + where L: PipelineLayoutDesc +{ #[inline] fn num_sets(&self) -> usize { self.layout.num_sets() @@ -1175,7 +1487,9 @@ unsafe impl PipelineLayoutDesc for GraphicsPipeline where } } -unsafe impl PipelineLayoutDescNames for GraphicsPipeline where L: PipelineLayoutDescNames { +unsafe impl PipelineLayoutDescNames for GraphicsPipeline + where L: PipelineLayoutDescNames +{ #[inline] fn descriptor_by_name(&self, name: &str) -> Option<(usize, usize)> { self.layout.descriptor_by_name(name) @@ -1270,12 +1584,14 @@ impl Drop for Inner { /// Trait implemented on objects that reference a graphics pipeline. Can be made into a trait /// object. pub unsafe trait GraphicsPipelineAbstract: PipelineLayoutAbstract + RenderPassAbstract + VertexSource>> { - /// Returns an opaque object that represents the inside of the graphics pipeline. +/// Returns an opaque object that represents the inside of the graphics pipeline. fn inner(&self) -> GraphicsPipelineSys; } unsafe impl GraphicsPipelineAbstract for GraphicsPipeline - where L: PipelineLayoutAbstract, Rp: RenderPassAbstract, Mv: VertexSource>> + where L: PipelineLayoutAbstract, + Rp: RenderPassAbstract, + Mv: VertexSource>> { #[inline] fn inner(&self) -> GraphicsPipelineSys { @@ -1284,7 +1600,8 @@ unsafe impl GraphicsPipelineAbstract for GraphicsPipeline } unsafe impl GraphicsPipelineAbstract for T - where T: SafeDeref, T::Target: GraphicsPipelineAbstract + where T: SafeDeref, + T::Target: GraphicsPipelineAbstract { #[inline] fn inner(&self) -> GraphicsPipelineSys { @@ -1312,9 +1629,9 @@ unsafe impl VertexDefinition for GraphicsPipeline type AttribsIter = >::AttribsIter; #[inline] - fn definition(&self, interface: &I) -> Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError> - { + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError> { self.vertex_definition.definition(interface) } } @@ -1346,7 +1663,7 @@ pub enum GraphicsPipelineCreationError { /// The interface between the vertex shader and the fragment shader mismatches. VertexFragmentStagesMismatch(ShaderInterfaceMismatchError), - /// The interface between the tessellation control shader and the tessellation evaluation + /// The interface between the tessellation control shader and the tessellation evaluation /// shader mismatches. TessControlTessEvalStagesMismatch(ShaderInterfaceMismatchError), @@ -1407,7 +1724,7 @@ pub enum GraphicsPipelineCreationError { /// The user requested to use primitive restart, but the primitive topology doesn't support it. PrimitiveDoesntSupportPrimitiveRestart { /// The topology that doesn't support primitive restart. - primitive: PrimitiveTopology + primitive: PrimitiveTopology, }, /// The `multi_viewport` feature must be enabled in order to use multiple viewports at once. @@ -1418,7 +1735,7 @@ pub enum GraphicsPipelineCreationError { /// Maximum allowed value. max: u32, /// Value that was passed. - obtained: u32 + obtained: u32, }, /// The maximum dimensions of viewports has been exceeded. @@ -1625,7 +1942,7 @@ impl error::Error for GraphicsPipelineCreationError { GraphicsPipelineCreationError::TessEvalFragmentStagesMismatch(ref err) => Some(err), GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(ref err) => Some(err), GraphicsPipelineCreationError::IncompatibleVertexDefinition(ref err) => Some(err), - _ => None + _ => None, } } } @@ -1668,7 +1985,7 @@ impl From for GraphicsPipelineCreationError { err @ Error::OutOfDeviceMemory => { GraphicsPipelineCreationError::OomError(OomError::from(err)) }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } diff --git a/vulkano/src/pipeline/input_assembly.rs b/vulkano/src/pipeline/input_assembly.rs index 8a0a16b9..dd734dd5 100644 --- a/vulkano/src/pipeline/input_assembly.rs +++ b/vulkano/src/pipeline/input_assembly.rs @@ -11,6 +11,7 @@ //! //! The input assembly is the stage where lists of vertices are turned into primitives. //! + use vk; /// How the input assembly stage should behave. @@ -67,10 +68,14 @@ impl Into for PrimitiveTopology { PrimitiveTopology::TriangleList => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, PrimitiveTopology::TriangleStrip => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, PrimitiveTopology::TriangleFan => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, - PrimitiveTopology::LineListWithAdjacency => vk::PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, - PrimitiveTopology::LineStripWithAdjacency => vk::PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, - PrimitiveTopology::TriangleListWithAdjacency => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, - PrimitiveTopology::TriangleStripWithAdjacency => vk::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, + PrimitiveTopology::LineListWithAdjacency => + vk::PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + PrimitiveTopology::LineStripWithAdjacency => + vk::PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + PrimitiveTopology::TriangleListWithAdjacency => + vk::PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, + PrimitiveTopology::TriangleStripWithAdjacency => + vk::PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, PrimitiveTopology::PatchList { .. } => vk::PRIMITIVE_TOPOLOGY_PATCH_LIST, } } @@ -86,7 +91,7 @@ impl PrimitiveTopology { PrimitiveTopology::TriangleFan => true, PrimitiveTopology::LineStripWithAdjacency => true, PrimitiveTopology::TriangleStripWithAdjacency => true, - _ => false + _ => false, } } } diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index 90bf8a5c..9c6582a7 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -25,7 +25,7 @@ //! write pixels to a framebuffer). //! //! # Creating a compute pipeline. -//! +//! //! In order to create a compute pipeline, you first need a *shader entry point*. //! //! TODO: write the rest diff --git a/vulkano/src/pipeline/raster.rs b/vulkano/src/pipeline/raster.rs index a3fd4ea5..db61eb08 100644 --- a/vulkano/src/pipeline/raster.rs +++ b/vulkano/src/pipeline/raster.rs @@ -8,10 +8,11 @@ // according to those terms. //! Stage when triangles are turned into pixels. -//! +//! //! The rasterization is the stage when collections of triangles are turned into collections //! of pixels or samples. //! + use vk; /// State of the rasterizer. @@ -71,7 +72,7 @@ impl DepthBiasControl { pub fn is_dynamic(&self) -> bool { match *self { DepthBiasControl::Dynamic => true, - _ => false + _ => false, } } } diff --git a/vulkano/src/pipeline/shader.rs b/vulkano/src/pipeline/shader.rs index dc065e33..920995dc 100644 --- a/vulkano/src/pipeline/shader.rs +++ b/vulkano/src/pipeline/shader.rs @@ -8,17 +8,18 @@ // according to those terms. //! Stage of a graphics pipeline. -//! +//! //! In Vulkan, shaders are grouped in *shader modules*. Each shader module is built from SPIR-V //! code and can contain one or more entry points. Note that for the moment the official //! GLSL-to-SPIR-V compiler does not support multiple entry points. -//! +//! //! The vulkano library does not provide any functionnality that checks and introspects the SPIR-V //! code, therefore the whole shader-related API is unsafe. You are encouraged to use the //! `vulkano-shaders` crate that will generate Rust code that wraps around vulkano's shaders API. use std::borrow::Cow; use std::error; +use std::ffi::CStr; use std::fmt; use std::iter; use std::iter::Empty as EmptyIter; @@ -27,16 +28,15 @@ use std::mem; use std::ops::Range; use std::ptr; use std::sync::Arc; -use std::ffi::CStr; use format::Format; use pipeline::input_assembly::PrimitiveTopology; -use device::Device; use OomError; -use VulkanObject; use SafeDeref; +use VulkanObject; use check_errors; +use device::Device; use vk; /// Contains SPIR-V code with one or more entry points. @@ -44,14 +44,18 @@ use vk; /// Note that it is advised to wrap around a `ShaderModule` with a struct that is different for /// each shader. #[derive(Debug)] -pub struct ShaderModule

> where P: SafeDeref { +pub struct ShaderModule

> + where P: SafeDeref +{ // The module. module: vk::ShaderModule, // Pointer to the device. device: P, } -impl

ShaderModule

where P: SafeDeref { +impl

ShaderModule

+ where P: SafeDeref +{ /// Builds a new shader module from SPIR-V. /// /// # Safety @@ -67,22 +71,24 @@ impl

ShaderModule

where P: SafeDeref { let infos = vk::ShaderModuleCreateInfo { sType: vk::STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved codeSize: spirv.len(), pCode: spirv.as_ptr() as *const _, }; let vk = device.pointers(); let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateShaderModule(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateShaderModule(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(ShaderModule { - module: module, - device: device, - })) + module: module, + device: device, + })) } /// Gets access to an entry point contained in this module. @@ -97,10 +103,9 @@ impl

ShaderModule

where P: SafeDeref { /// - The input, output and layout must correctly describe the input, output and layout used /// by this stage. /// - pub unsafe fn vertex_shader_entry_point<'a, S, I, O, L> - (&'a self, name: &'a CStr, input: I, output: O, layout: L) - -> VertexShaderEntryPoint<'a, S, I, O, L, P> - { + pub unsafe fn vertex_shader_entry_point<'a, S, I, O, L>( + &'a self, name: &'a CStr, input: I, output: O, layout: L) + -> VertexShaderEntryPoint<'a, S, I, O, L, P> { VertexShaderEntryPoint { module: self, name: name, @@ -123,10 +128,9 @@ impl

ShaderModule

where P: SafeDeref { /// - The input, output and layout must correctly describe the input, output and layout used /// by this stage. /// - pub unsafe fn tess_control_shader_entry_point<'a, S, I, O, L> - (&'a self, name: &'a CStr, input: I, output: O, layout: L) - -> TessControlShaderEntryPoint<'a, S, I, O, L, P> - { + pub unsafe fn tess_control_shader_entry_point<'a, S, I, O, L>( + &'a self, name: &'a CStr, input: I, output: O, layout: L) + -> TessControlShaderEntryPoint<'a, S, I, O, L, P> { TessControlShaderEntryPoint { module: self, name: name, @@ -149,10 +153,9 @@ impl

ShaderModule

where P: SafeDeref { /// - The input, output and layout must correctly describe the input, output and layout used /// by this stage. /// - pub unsafe fn tess_evaluation_shader_entry_point<'a, S, I, O, L> - (&'a self, name: &'a CStr, input: I, output: O, layout: L) - -> TessEvaluationShaderEntryPoint<'a, S, I, O, L, P> - { + pub unsafe fn tess_evaluation_shader_entry_point<'a, S, I, O, L>( + &'a self, name: &'a CStr, input: I, output: O, layout: L) + -> TessEvaluationShaderEntryPoint<'a, S, I, O, L, P> { TessEvaluationShaderEntryPoint { module: self, name: name, @@ -175,10 +178,10 @@ impl

ShaderModule

where P: SafeDeref { /// - The input, output and layout must correctly describe the input, output and layout used /// by this stage. /// - pub unsafe fn geometry_shader_entry_point<'a, S, I, O, L> - (&'a self, name: &'a CStr, primitives: GeometryShaderExecutionMode, input: I, - output: O, layout: L) -> GeometryShaderEntryPoint<'a, S, I, O, L, P> - { + pub unsafe fn geometry_shader_entry_point<'a, S, I, O, L>( + &'a self, name: &'a CStr, primitives: GeometryShaderExecutionMode, input: I, output: O, + layout: L) + -> GeometryShaderEntryPoint<'a, S, I, O, L, P> { GeometryShaderEntryPoint { module: self, name: name, @@ -202,10 +205,9 @@ impl

ShaderModule

where P: SafeDeref { /// - The input, output and layout must correctly describe the input, output and layout used /// by this stage. /// - pub unsafe fn fragment_shader_entry_point<'a, S, I, O, L> - (&'a self, name: &'a CStr, input: I, output: O, layout: L) - -> FragmentShaderEntryPoint<'a, S, I, O, L, P> - { + pub unsafe fn fragment_shader_entry_point<'a, S, I, O, L>( + &'a self, name: &'a CStr, input: I, output: O, layout: L) + -> FragmentShaderEntryPoint<'a, S, I, O, L, P> { FragmentShaderEntryPoint { module: self, name: name, @@ -229,8 +231,7 @@ impl

ShaderModule

where P: SafeDeref { /// #[inline] pub unsafe fn compute_shader_entry_point<'a, S, L>(&'a self, name: &'a CStr, layout: L) - -> ComputeShaderEntryPoint<'a, S, L, P> - { + -> ComputeShaderEntryPoint<'a, S, L, P> { ComputeShaderEntryPoint { module: self, name: name, @@ -240,7 +241,9 @@ impl

ShaderModule

where P: SafeDeref { } } -unsafe impl

VulkanObject for ShaderModule

where P: SafeDeref { +unsafe impl

VulkanObject for ShaderModule

+ where P: SafeDeref +{ type Object = vk::ShaderModule; #[inline] @@ -249,7 +252,9 @@ unsafe impl

VulkanObject for ShaderModule

where P: SafeDeref Drop for ShaderModule

where P: SafeDeref { +impl

Drop for ShaderModule

+ where P: SafeDeref +{ #[inline] fn drop(&mut self) { unsafe { @@ -263,7 +268,7 @@ impl

Drop for ShaderModule

where P: SafeDeref { /// /// Can be obtained by calling `vertex_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct VertexShaderEntryPoint<'a, S, I, O, L, P = Arc> +pub struct VertexShaderEntryPoint<'a, S, I, O, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -313,7 +318,7 @@ impl<'a, S, I, O, L, P> VertexShaderEntryPoint<'a, S, I, O, L, P> /// /// Can be obtained by calling `tess_control_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct TessControlShaderEntryPoint<'a, S, I, O, L, P = Arc> +pub struct TessControlShaderEntryPoint<'a, S, I, O, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -324,7 +329,7 @@ pub struct TessControlShaderEntryPoint<'a, S, I, O, L, P = Arc> marker: PhantomData, } -impl<'a, S, I, O, L, P> TessControlShaderEntryPoint<'a, S, I, O, L, P> +impl<'a, S, I, O, L, P> TessControlShaderEntryPoint<'a, S, I, O, L, P> where P: 'a + SafeDeref { /// Returns the module this entry point comes from. @@ -362,7 +367,7 @@ impl<'a, S, I, O, L, P> TessControlShaderEntryPoint<'a, S, I, O, L, P> /// /// Can be obtained by calling `tess_evaluation_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct TessEvaluationShaderEntryPoint<'a, S, I, O, L, P = Arc> +pub struct TessEvaluationShaderEntryPoint<'a, S, I, O, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -373,7 +378,7 @@ pub struct TessEvaluationShaderEntryPoint<'a, S, I, O, L, P = Arc> marker: PhantomData, } -impl<'a, S, I, O, L, P> TessEvaluationShaderEntryPoint<'a, S, I, O, L, P> +impl<'a, S, I, O, L, P> TessEvaluationShaderEntryPoint<'a, S, I, O, L, P> where P: 'a + SafeDeref { /// Returns the module this entry point comes from. @@ -411,7 +416,7 @@ impl<'a, S, I, O, L, P> TessEvaluationShaderEntryPoint<'a, S, I, O, L, P> /// /// Can be obtained by calling `geometry_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct GeometryShaderEntryPoint<'a, S, I, O, L, P = Arc> +pub struct GeometryShaderEntryPoint<'a, S, I, O, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -423,7 +428,7 @@ pub struct GeometryShaderEntryPoint<'a, S, I, O, L, P = Arc> marker: PhantomData, } -impl<'a, S, I, O, L, P> GeometryShaderEntryPoint<'a, S, I, O, L, P> +impl<'a, S, I, O, L, P> GeometryShaderEntryPoint<'a, S, I, O, L, P> where P: 'a + SafeDeref { /// Returns the module this entry point comes from. @@ -502,7 +507,7 @@ impl GeometryShaderExecutionMode { /// /// Can be obtained by calling `fragment_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct FragmentShaderEntryPoint<'a, S, I, O, L, P = Arc> +pub struct FragmentShaderEntryPoint<'a, S, I, O, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -513,7 +518,7 @@ pub struct FragmentShaderEntryPoint<'a, S, I, O, L, P = Arc> marker: PhantomData, } -impl<'a, S, I, O, L, P> FragmentShaderEntryPoint<'a, S, I, O, L, P> +impl<'a, S, I, O, L, P> FragmentShaderEntryPoint<'a, S, I, O, L, P> where P: 'a + SafeDeref { /// Returns the module this entry point comes from. @@ -551,7 +556,7 @@ impl<'a, S, I, O, L, P> FragmentShaderEntryPoint<'a, S, I, O, L, P> /// /// Can be obtained by calling `compute_shader_entry_point()` on the shader module. #[derive(Debug, Copy, Clone)] -pub struct ComputeShaderEntryPoint<'a, S, L, P = Arc> +pub struct ComputeShaderEntryPoint<'a, S, L, P = Arc> where P: 'a + SafeDeref { module: &'a ShaderModule

, @@ -560,7 +565,7 @@ pub struct ComputeShaderEntryPoint<'a, S, L, P = Arc> marker: PhantomData, } -impl<'a, S, L, P> ComputeShaderEntryPoint<'a, S, L, P> +impl<'a, S, L, P> ComputeShaderEntryPoint<'a, S, L, P> where P: 'a + SafeDeref { /// Returns the module this entry point comes from. @@ -624,14 +629,17 @@ unsafe impl ShaderInterfaceDef for EmptyShaderInterfaceDef { /// Extension trait for `ShaderInterfaceDef` that specifies that the interface is potentially /// compatible with another one. -pub unsafe trait ShaderInterfaceDefMatch: ShaderInterfaceDef where I: ShaderInterfaceDef { +pub unsafe trait ShaderInterfaceDefMatch: ShaderInterfaceDef + where I: ShaderInterfaceDef +{ /// Returns `Ok` if the two definitions match. fn matches(&self, other: &I) -> Result<(), ShaderInterfaceMismatchError>; } // TODO: turn this into a default impl that can be specialized unsafe impl ShaderInterfaceDefMatch for T - where T: ShaderInterfaceDef, I: ShaderInterfaceDef + where T: ShaderInterfaceDef, + I: ShaderInterfaceDef { fn matches(&self, other: &I) -> Result<(), ShaderInterfaceMismatchError> { if self.elements().len() != other.elements().len() { @@ -640,8 +648,12 @@ unsafe impl ShaderInterfaceDefMatch for T for a in self.elements() { for loc in a.location.clone() { - let b = match other.elements().find(|e| loc >= e.location.start && loc < e.location.end) { - None => return Err(ShaderInterfaceMismatchError::MissingElement { location: loc }), + let b = match other + .elements() + .find(|e| loc >= e.location.start && loc < e.location.end) { + None => return Err(ShaderInterfaceMismatchError::MissingElement { + location: loc, + }), Some(b) => b, }; @@ -674,11 +686,11 @@ impl error::Error for ShaderInterfaceMismatchError { #[inline] fn description(&self) -> &str { match *self { - ShaderInterfaceMismatchError::ElementsCountMismatch => "the number of elements \ - mismatches", + ShaderInterfaceMismatchError::ElementsCountMismatch => + "the number of elements mismatches", ShaderInterfaceMismatchError::MissingElement { .. } => "an element is missing", - ShaderInterfaceMismatchError::FormatMismatch => "the format of an element does not \ - match", + ShaderInterfaceMismatchError::FormatMismatch => + "the format of an element does not match", } } } diff --git a/vulkano/src/pipeline/vertex/definition.rs b/vulkano/src/pipeline/vertex/definition.rs index 09416097..31e67ede 100644 --- a/vulkano/src/pipeline/vertex/definition.rs +++ b/vulkano/src/pipeline/vertex/definition.rs @@ -11,14 +11,15 @@ use std::error; use std::fmt; use std::sync::Arc; +use SafeDeref; use buffer::BufferAccess; use format::Format; use pipeline::vertex::VertexMemberTy; -use SafeDeref; use vk; /// Trait for types that describe the definition of the vertex input used by a graphics pipeline. -pub unsafe trait VertexDefinition: VertexSource>> { +pub unsafe trait VertexDefinition + : VertexSource>> { /// Iterator that returns the offset, the stride (in bytes) and input rate of each buffer. type BuffersIter: ExactSizeIterator; /// Iterator that returns the attribute location, buffer id, and infos. @@ -26,18 +27,22 @@ pub unsafe trait VertexDefinition: VertexSource Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError>; + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError>; } -unsafe impl VertexDefinition for T where T: SafeDeref, T::Target: VertexDefinition { +unsafe impl VertexDefinition for T + where T: SafeDeref, + T::Target: VertexDefinition +{ type BuffersIter = >::BuffersIter; type AttribsIter = >::AttribsIter; #[inline] - fn definition(&self, interface: &I) -> Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError> - { + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError> { (**self).definition(interface) } } @@ -111,7 +116,10 @@ pub unsafe trait VertexSource { fn decode(&self, L) -> (Vec>, usize, usize); } -unsafe impl VertexSource for T where T: SafeDeref, T::Target: VertexSource { +unsafe impl VertexSource for T + where T: SafeDeref, + T::Target: VertexSource +{ #[inline] fn decode(&self, list: L) -> (Vec>, usize, usize) { (**self).decode(list) diff --git a/vulkano/src/pipeline/vertex/mod.rs b/vulkano/src/pipeline/vertex/mod.rs index 62c28fd5..349910a3 100644 --- a/vulkano/src/pipeline/vertex/mod.rs +++ b/vulkano/src/pipeline/vertex/mod.rs @@ -44,21 +44,21 @@ //! use vulkano::pipeline::vertex::; //! # let device: Arc = return; //! # let queue: Arc = return; -//! +//! //! struct Vertex { //! position: [f32; 2] //! } -//! +//! //! impl_vertex!(Vertex, position); -//! +//! //! let usage = BufferUsage { //! vertex_buffer: true, //! .. BufferUsage::none() //! }; -//! +//! //! let vertex_buffer = BufferAccess::<[Vertex], _>::array(&device, 128, &usage, HostVisible, &queue) //! .expect("failed to create buffer"); -//! +//! //! // TODO: finish example //! # } //! ``` diff --git a/vulkano/src/pipeline/vertex/one_one.rs b/vulkano/src/pipeline/vertex/one_one.rs index 717ba547..80ce8e87 100644 --- a/vulkano/src/pipeline/vertex/one_one.rs +++ b/vulkano/src/pipeline/vertex/one_one.rs @@ -28,18 +28,22 @@ pub struct OneVertexOneInstanceDefinition(pub PhantomData<(T, U)>); impl OneVertexOneInstanceDefinition { #[inline] - pub fn new() -> OneVertexOneInstanceDefinition { OneVertexOneInstanceDefinition(PhantomData) } + pub fn new() -> OneVertexOneInstanceDefinition { + OneVertexOneInstanceDefinition(PhantomData) + } } unsafe impl VertexDefinition for OneVertexOneInstanceDefinition - where T: Vertex, U: Vertex, I: ShaderInterfaceDef + where T: Vertex, + U: Vertex, + I: ShaderInterfaceDef { type BuffersIter = VecIntoIter<(u32, usize, InputRate)>; type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>; - fn definition(&self, interface: &I) -> Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError> - { + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError> { let attrib = { let mut attribs = Vec::with_capacity(interface.elements().len()); for e in interface.elements() { @@ -51,43 +55,52 @@ unsafe impl VertexDefinition for OneVertexOneInstanceDefinition(), InputRate::Vertex), - (1, mem::size_of::(), InputRate::Instance) + (1, mem::size_of::(), InputRate::Instance), ].into_iter(); Ok((buffers, attrib)) } } -unsafe impl VertexSource>> for OneVertexOneInstanceDefinition - where T: Vertex, U: Vertex +unsafe impl VertexSource>> + for OneVertexOneInstanceDefinition + where T: Vertex, + U: Vertex { #[inline] - fn decode(&self, mut source: Vec>) -> (Vec>, usize, usize) { + fn decode(&self, mut source: Vec>) + -> (Vec>, usize, usize) { // FIXME: safety assert_eq!(source.len(), 2); let len = source[0].size() / mem::size_of::(); @@ -99,8 +112,10 @@ unsafe impl VertexSource>> for OneVert } unsafe impl<'a, T, U, Bt, Bu> VertexSource<(Bt, Bu)> for OneVertexOneInstanceDefinition - where T: Vertex, Bt: TypedBufferAccess + Send + Sync + 'static, - U: Vertex, Bu: TypedBufferAccess + Send + Sync + 'static + where T: Vertex, + Bt: TypedBufferAccess + Send + Sync + 'static, + U: Vertex, + Bu: TypedBufferAccess + Send + Sync + 'static { #[inline] fn decode(&self, source: (Bt, Bu)) -> (Vec>, usize, usize) { diff --git a/vulkano/src/pipeline/vertex/single.rs b/vulkano/src/pipeline/vertex/single.rs index 11b174eb..e56ab26f 100644 --- a/vulkano/src/pipeline/vertex/single.rs +++ b/vulkano/src/pipeline/vertex/single.rs @@ -28,18 +28,21 @@ pub struct SingleBufferDefinition(pub PhantomData); impl SingleBufferDefinition { #[inline] - pub fn new() -> SingleBufferDefinition { SingleBufferDefinition(PhantomData) } + pub fn new() -> SingleBufferDefinition { + SingleBufferDefinition(PhantomData) + } } unsafe impl VertexDefinition for SingleBufferDefinition - where T: Vertex, I: ShaderInterfaceDef + where T: Vertex, + I: ShaderInterfaceDef { type BuffersIter = OptionIntoIter<(u32, usize, InputRate)>; type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>; - fn definition(&self, interface: &I) -> Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError> - { + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError> { let attrib = { let mut attribs = Vec::with_capacity(interface.elements().len()); for e in interface.elements() { @@ -48,28 +51,34 @@ unsafe impl VertexDefinition for SingleBufferDefinition let infos = match ::member(name) { Some(m) => m, None => return Err(IncompatibleVertexDefinitionError::MissingAttribute { - attribute: name.clone().into_owned() - }) + attribute: name.clone().into_owned(), + }), }; - if !infos.ty.matches(infos.array_size, e.format, + if !infos.ty.matches(infos.array_size, + e.format, e.location.end - e.location.start) { return Err(IncompatibleVertexDefinitionError::FormatMismatch { - attribute: name.clone().into_owned(), - shader: (e.format, (e.location.end - e.location.start) as usize), - definition: (infos.ty, infos.array_size), - }) + attribute: name.clone().into_owned(), + shader: (e.format, (e.location.end - e.location.start) as usize), + definition: (infos.ty, infos.array_size), + }); } let mut offset = infos.offset; for loc in e.location.clone() { - attribs.push((loc, 0, AttributeInfo { offset: offset, format: e.format })); + attribs.push((loc, + 0, + AttributeInfo { + offset: offset, + format: e.format, + })); offset += e.format.size().unwrap(); } } attribs - }.into_iter(); // TODO: meh + }.into_iter(); // TODO: meh let buffers = Some((0, mem::size_of::(), InputRate::Vertex)).into_iter(); Ok((buffers, attrib)) @@ -80,7 +89,8 @@ unsafe impl VertexSource>> for SingleBuff where V: Vertex { #[inline] - fn decode(&self, mut source: Vec>) -> (Vec>, usize, usize) { + fn decode(&self, mut source: Vec>) + -> (Vec>, usize, usize) { // FIXME: safety assert_eq!(source.len(), 1); let len = source[0].size() / mem::size_of::(); @@ -89,7 +99,8 @@ unsafe impl VertexSource>> for SingleBuff } unsafe impl<'a, B, V> VertexSource for SingleBufferDefinition - where B: TypedBufferAccess + Send + Sync + 'static, V: Vertex + where B: TypedBufferAccess + Send + Sync + 'static, + V: Vertex { #[inline] fn decode(&self, source: B) -> (Vec>, usize, usize) { diff --git a/vulkano/src/pipeline/vertex/two.rs b/vulkano/src/pipeline/vertex/two.rs index e8b8170c..f035e8cd 100644 --- a/vulkano/src/pipeline/vertex/two.rs +++ b/vulkano/src/pipeline/vertex/two.rs @@ -28,18 +28,22 @@ pub struct TwoBuffersDefinition(pub PhantomData<(T, U)>); impl TwoBuffersDefinition { #[inline] - pub fn new() -> TwoBuffersDefinition { TwoBuffersDefinition(PhantomData) } + pub fn new() -> TwoBuffersDefinition { + TwoBuffersDefinition(PhantomData) + } } unsafe impl VertexDefinition for TwoBuffersDefinition - where T: Vertex, U: Vertex, I: ShaderInterfaceDef + where T: Vertex, + U: Vertex, + I: ShaderInterfaceDef { type BuffersIter = VecIntoIter<(u32, usize, InputRate)>; type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>; - fn definition(&self, interface: &I) -> Result<(Self::BuffersIter, Self::AttribsIter), - IncompatibleVertexDefinitionError> - { + fn definition( + &self, interface: &I) + -> Result<(Self::BuffersIter, Self::AttribsIter), IncompatibleVertexDefinitionError> { let attrib = { let mut attribs = Vec::with_capacity(interface.elements().len()); for e in interface.elements() { @@ -51,32 +55,38 @@ unsafe impl VertexDefinition for TwoBuffersDefinition (infos, 1) } else { return Err(IncompatibleVertexDefinitionError::MissingAttribute { - attribute: name.clone().into_owned() - }); + attribute: name.clone().into_owned(), + }); }; - if !infos.ty.matches(infos.array_size, e.format, + if !infos.ty.matches(infos.array_size, + e.format, e.location.end - e.location.start) { return Err(IncompatibleVertexDefinitionError::FormatMismatch { - attribute: name.clone().into_owned(), - shader: (e.format, (e.location.end - e.location.start) as usize), - definition: (infos.ty, infos.array_size), - }) + attribute: name.clone().into_owned(), + shader: (e.format, (e.location.end - e.location.start) as usize), + definition: (infos.ty, infos.array_size), + }); } let mut offset = infos.offset; for loc in e.location.clone() { - attribs.push((loc, buf_offset, AttributeInfo { offset: offset, format: e.format })); + attribs.push((loc, + buf_offset, + AttributeInfo { + offset: offset, + format: e.format, + })); offset += e.format.size().unwrap(); } } attribs - }.into_iter(); // TODO: meh + }.into_iter(); // TODO: meh let buffers = vec![ (0, mem::size_of::(), InputRate::Vertex), - (1, mem::size_of::(), InputRate::Vertex) + (1, mem::size_of::(), InputRate::Vertex), ].into_iter(); Ok((buffers, attrib)) @@ -84,21 +94,29 @@ unsafe impl VertexDefinition for TwoBuffersDefinition } unsafe impl VertexSource>> for TwoBuffersDefinition - where T: Vertex, U: Vertex + where T: Vertex, + U: Vertex { #[inline] - fn decode(&self, source: Vec>) -> (Vec>, usize, usize) { - unimplemented!() // FIXME: implement + fn decode(&self, source: Vec>) + -> (Vec>, usize, usize) { + unimplemented!() // FIXME: implement } } unsafe impl<'a, T, U, Bt, Bu> VertexSource<(Bt, Bu)> for TwoBuffersDefinition - where T: Vertex, Bt: TypedBufferAccess + Send + Sync + 'static, - U: Vertex, Bu: TypedBufferAccess + Send + Sync + 'static + where T: Vertex, + Bt: TypedBufferAccess + Send + Sync + 'static, + U: Vertex, + Bu: TypedBufferAccess + Send + Sync + 'static { #[inline] fn decode(&self, source: (Bt, Bu)) -> (Vec>, usize, usize) { - let vertices = [source.0.len(), source.1.len()].iter().cloned().min().unwrap(); + let vertices = [source.0.len(), source.1.len()] + .iter() + .cloned() + .min() + .unwrap(); (vec![Box::new(source.0) as Box<_>, Box::new(source.1) as Box<_>], vertices, 1) } } diff --git a/vulkano/src/pipeline/viewport.rs b/vulkano/src/pipeline/viewport.rs index bd93219b..5c3c9a24 100644 --- a/vulkano/src/pipeline/viewport.rs +++ b/vulkano/src/pipeline/viewport.rs @@ -47,6 +47,7 @@ //! //! In all cases the number of viewports and scissor boxes must be the same. //! + use std::ops::Range; use vk; @@ -121,7 +122,7 @@ impl ViewportsState { /// State of a single viewport. // FIXME: check that: // x + width must be less than or equal to viewportBoundsRange[0] -// y + height must be less than or equal to viewportBoundsRange[1] +// y + height must be less than or equal to viewportBoundsRange[1] #[derive(Debug, Clone)] pub struct Viewport { /// Coordinates in pixels of the top-left hand corner of the viewport. @@ -158,7 +159,7 @@ impl Into for Viewport { /// State of a single scissor box. // FIXME: add a check: // Evaluation of (offset.x + extent.width) must not cause a signed integer addition overflow -// Evaluation of (offset.y + extent.height) must not cause a signed integer addition overflow +// Evaluation of (offset.y + extent.height) must not cause a signed integer addition overflow #[derive(Debug, Copy, Clone)] pub struct Scissor { /// Coordinates in pixels of the top-left hand corner of the box. diff --git a/vulkano/src/query.rs b/vulkano/src/query.rs index 543fe918..a288188d 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query.rs @@ -8,7 +8,7 @@ // according to those terms. //! This module provides support for query pools. -//! +//! //! In Vulkan, queries are not created individually. Instead you manipulate **query pools**, which //! represent a collection of queries. Whenever you use a query, you have to specify both the query //! pool and the slot id within that query pool. @@ -21,24 +21,27 @@ use std::sync::Arc; use device::Device; -use check_errors; use Error; use OomError; use SafeDeref; use VulkanObject; +use check_errors; use vk; -pub struct UnsafeQueryPool

> where P: SafeDeref { +pub struct UnsafeQueryPool

> + where P: SafeDeref +{ pool: vk::QueryPool, device: P, num_slots: u32, } -impl

UnsafeQueryPool

where P: SafeDeref { +impl

UnsafeQueryPool

+ where P: SafeDeref +{ /// Builds a new query pool. pub fn new(device: P, ty: QueryType, num_slots: u32) - -> Result, QueryPoolCreationError> - { + -> Result, QueryPoolCreationError> { let (vk_ty, statistics) = match ty { QueryType::Occlusion => (vk::QUERY_TYPE_OCCLUSION, 0), QueryType::Timestamp => (vk::QUERY_TYPE_TIMESTAMP, 0), @@ -55,7 +58,7 @@ impl

UnsafeQueryPool

where P: SafeDeref { let infos = vk::QueryPoolCreateInfo { sType: vk::STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved queryType: vk_ty, queryCount: num_slots, pipelineStatistics: statistics, @@ -63,16 +66,18 @@ impl

UnsafeQueryPool

where P: SafeDeref { let mut output = mem::uninitialized(); let vk = device.pointers(); - try!(check_errors(vk.CreateQueryPool(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateQueryPool(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(UnsafeQueryPool { - pool: pool, - device: device, - num_slots: num_slots, - }) + pool: pool, + device: device, + num_slots: num_slots, + }) } /// Returns the number of slots of that query pool. @@ -169,7 +174,9 @@ impl Into for QueryPipelineStatisticFlags { } } -impl

Drop for UnsafeQueryPool

where P: SafeDeref { +impl

Drop for UnsafeQueryPool

+ where P: SafeDeref +{ #[inline] fn drop(&mut self) { unsafe { @@ -204,7 +211,7 @@ impl error::Error for QueryPoolCreationError { fn cause(&self) -> Option<&error::Error> { match *self { QueryPoolCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -229,7 +236,7 @@ impl From for QueryPoolCreationError { match err { err @ Error::OutOfHostMemory => QueryPoolCreationError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => QueryPoolCreationError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -240,18 +247,16 @@ pub struct OcclusionQueriesPool { impl OcclusionQueriesPool { /// See the docs of new(). - pub fn raw(device: Arc, num_slots: u32) - -> Result - { + pub fn raw(device: Arc, num_slots: u32) -> Result { Ok(OcclusionQueriesPool { - inner: match UnsafeQueryPool::new(device, QueryType::Occlusion, num_slots) { - Ok(q) => q, - Err(QueryPoolCreationError::OomError(err)) => return Err(err), - Err(QueryPoolCreationError::PipelineStatisticsQueryFeatureNotEnabled) => { - unreachable!() - }, - } - }) + inner: match UnsafeQueryPool::new(device, QueryType::Occlusion, num_slots) { + Ok(q) => q, + Err(QueryPoolCreationError::OomError(err)) => return Err(err), + Err(QueryPoolCreationError::PipelineStatisticsQueryFeatureNotEnabled) => { + unreachable!() + }, + }, + }) } /// Builds a new query pool. @@ -261,10 +266,8 @@ impl OcclusionQueriesPool { /// - Panics if the device or host ran out of memory. /// #[inline] - pub fn new(device: Arc, num_slots: u32) - -> Arc - { - Arc::new(OcclusionQueriesPool::raw(device, num_slots).unwrap()) + pub fn new(device: Arc, num_slots: u32) -> Arc { + Arc::new(OcclusionQueriesPool::raw(device, num_slots).unwrap()) } /// Returns the number of slots of that query pool. @@ -301,7 +304,7 @@ mod tests { let ty = QueryType::PipelineStatistics(QueryPipelineStatisticFlags::none()); match UnsafeQueryPool::new(device, ty, 256) { Err(QueryPoolCreationError::PipelineStatisticsQueryFeatureNotEnabled) => (), - _ => panic!() + _ => panic!(), }; } } diff --git a/vulkano/src/sampler.rs b/vulkano/src/sampler.rs index 6edc5a78..90a55284 100644 --- a/vulkano/src/sampler.rs +++ b/vulkano/src/sampler.rs @@ -61,17 +61,18 @@ //! Samplers that don't use `ClampToBorder` are not concerned by these restrictions. //! // FIXME: restrictions aren't checked yet + use std::error; use std::fmt; use std::mem; use std::ptr; use std::sync::Arc; -use device::Device; use Error; use OomError; use VulkanObject; use check_errors; +use device::Device; use vk; pub use pipeline::depth_stencil::Compare; @@ -99,9 +100,18 @@ impl Sampler { /// #[inline] pub fn simple_repeat_linear(device: Arc) -> Arc { - Sampler::new(device, Filter::Linear, Filter::Linear, MipmapMode::Linear, - SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, - SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 1_000.0).unwrap() + Sampler::new(device, + Filter::Linear, + Filter::Linear, + MipmapMode::Linear, + SamplerAddressMode::Repeat, + SamplerAddressMode::Repeat, + SamplerAddressMode::Repeat, + 0.0, + 1.0, + 0.0, + 1_000.0) + .unwrap() } /// Shortcut for creating a sampler with linear sampling, that only uses the main level of @@ -115,9 +125,18 @@ impl Sampler { /// #[inline] pub fn simple_repeat_linear_no_mipmap(device: Arc) -> Arc { - Sampler::new(device, Filter::Linear, Filter::Linear, MipmapMode::Nearest, - SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, - SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 1.0).unwrap() + Sampler::new(device, + Filter::Linear, + Filter::Linear, + MipmapMode::Nearest, + SamplerAddressMode::Repeat, + SamplerAddressMode::Repeat, + SamplerAddressMode::Repeat, + 0.0, + 1.0, + 0.0, + 1.0) + .unwrap() } /// Creates a new `Sampler` with the given behavior. @@ -150,10 +169,19 @@ impl Sampler { mipmap_mode: MipmapMode, address_u: SamplerAddressMode, address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32, max_anisotropy: f32, min_lod: f32, max_lod: f32) - -> Result, SamplerCreationError> - { - Sampler::new_impl(device, mag_filter, min_filter, mipmap_mode, address_u, address_v, - address_w, mip_lod_bias, max_anisotropy, min_lod, max_lod, None) + -> Result, SamplerCreationError> { + Sampler::new_impl(device, + mag_filter, + min_filter, + mipmap_mode, + address_u, + address_v, + address_w, + mip_lod_bias, + max_anisotropy, + min_lod, + max_lod, + None) } /// Creates a new `Sampler` with the given behavior. @@ -175,20 +203,29 @@ impl Sampler { #[inline(always)] pub fn compare(device: Arc, mag_filter: Filter, min_filter: Filter, mipmap_mode: MipmapMode, address_u: SamplerAddressMode, - address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32, - max_anisotropy: f32, min_lod: f32, max_lod: f32, compare: Compare) - -> Result, SamplerCreationError> - { - Sampler::new_impl(device, mag_filter, min_filter, mipmap_mode, address_u, address_v, - address_w, mip_lod_bias, max_anisotropy, min_lod, max_lod, Some(compare)) + address_v: SamplerAddressMode, address_w: SamplerAddressMode, + mip_lod_bias: f32, max_anisotropy: f32, min_lod: f32, max_lod: f32, + compare: Compare) + -> Result, SamplerCreationError> { + Sampler::new_impl(device, + mag_filter, + min_filter, + mipmap_mode, + address_u, + address_v, + address_w, + mip_lod_bias, + max_anisotropy, + min_lod, + max_lod, + Some(compare)) } fn new_impl(device: Arc, mag_filter: Filter, min_filter: Filter, mipmap_mode: MipmapMode, address_u: SamplerAddressMode, address_v: SamplerAddressMode, address_w: SamplerAddressMode, mip_lod_bias: f32, max_anisotropy: f32, min_lod: f32, max_lod: f32, compare: Option) - -> Result, SamplerCreationError> - { + -> Result, SamplerCreationError> { assert!(max_anisotropy >= 1.0); assert!(min_lod <= max_lod); @@ -201,9 +238,9 @@ impl Sampler { let limit = device.physical_device().limits().max_sampler_anisotropy(); if max_anisotropy > limit { return Err(SamplerCreationError::AnisotropyLimitExceeded { - requested: max_anisotropy, - maximum: limit, - }); + requested: max_anisotropy, + maximum: limit, + }); } } @@ -212,16 +249,17 @@ impl Sampler { let limit = device.physical_device().limits().max_sampler_lod_bias(); if mip_lod_bias > limit { return Err(SamplerCreationError::MipLodBiasLimitExceeded { - requested: mip_lod_bias, - maximum: limit, - }); + requested: mip_lod_bias, + maximum: limit, + }); } } // Check MirrorClampToEdge extension support if [address_u, address_v, address_w] .iter() - .any(|&mode| mode == SamplerAddressMode::MirrorClampToEdge) { + .any(|&mode| mode == SamplerAddressMode::MirrorClampToEdge) + { if !device.loaded_extensions().khr_sampler_mirror_clamp_to_edge { return Err(SamplerCreationError::SamplerMirrorClampToEdgeExtensionNotEnabled); } @@ -230,12 +268,18 @@ impl Sampler { // Handling border color. let border_color = address_u.border_color(); let border_color = match (border_color, address_v.border_color()) { - (Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) }, + (Some(b1), Some(b2)) => { + assert_eq!(b1, b2); + Some(b1) + }, (None, b) => b, (b, None) => b, }; let border_color = match (border_color, address_w.border_color()) { - (Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) }, + (Some(b1), Some(b2)) => { + assert_eq!(b1, b2); + Some(b1) + }, (None, b) => b, (b, None) => b, }; @@ -245,7 +289,7 @@ impl Sampler { let infos = vk::SamplerCreateInfo { sType: vk::STRUCTURE_TYPE_SAMPLER_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved magFilter: mag_filter as u32, minFilter: min_filter as u32, mipmapMode: mipmap_mode as u32, @@ -253,9 +297,17 @@ impl Sampler { addressModeV: address_v.to_vk(), addressModeW: address_w.to_vk(), mipLodBias: mip_lod_bias, - anisotropyEnable: if max_anisotropy > 1.0 { vk::TRUE } else { vk::FALSE }, + anisotropyEnable: if max_anisotropy > 1.0 { + vk::TRUE + } else { + vk::FALSE + }, maxAnisotropy: max_anisotropy, - compareEnable: if compare.is_some() { vk::TRUE } else { vk:: FALSE }, + compareEnable: if compare.is_some() { + vk::TRUE + } else { + vk::FALSE + }, compareOp: compare.map(|c| c as u32).unwrap_or(0), minLod: min_lod, maxLod: max_lod, @@ -264,36 +316,39 @@ impl Sampler { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateSampler(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateSampler(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Sampler { - sampler: sampler, - device: device.clone(), - compare_mode: compare.is_some(), - unnormalized: false, - usable_with_float_formats: match border_color { - Some(BorderColor::FloatTransparentBlack) => true, - Some(BorderColor::FloatOpaqueBlack) => true, - Some(BorderColor::FloatOpaqueWhite) => true, - Some(_) => false, - None => true, - }, - usable_with_int_formats: compare.is_none() && match border_color { - Some(BorderColor::IntTransparentBlack) => true, - Some(BorderColor::IntOpaqueBlack) => true, - Some(BorderColor::IntOpaqueWhite) => true, - Some(_) => false, - None => true, - }, - usable_with_swizzling: match border_color { - Some(BorderColor::FloatOpaqueBlack) => false, - Some(BorderColor::IntOpaqueBlack) => false, - _ => true, - }, - })) + sampler: sampler, + device: device.clone(), + compare_mode: compare.is_some(), + unnormalized: false, + usable_with_float_formats: match border_color { + Some(BorderColor::FloatTransparentBlack) => true, + Some(BorderColor::FloatOpaqueBlack) => true, + Some(BorderColor::FloatOpaqueWhite) => true, + Some(_) => false, + None => true, + }, + usable_with_int_formats: compare.is_none() && + match border_color { + Some(BorderColor::IntTransparentBlack) => true, + Some(BorderColor::IntOpaqueBlack) => true, + Some(BorderColor::IntOpaqueWhite) => true, + Some(_) => false, + None => true, + }, + usable_with_swizzling: match border_color { + Some(BorderColor::FloatOpaqueBlack) => false, + Some(BorderColor::IntOpaqueBlack) => false, + _ => true, + }, + })) } /// Creates a sampler with unnormalized coordinates. This means that texture coordinates won't @@ -312,13 +367,15 @@ impl Sampler { pub fn unnormalized(device: Arc, filter: Filter, address_u: UnnormalizedSamplerAddressMode, address_v: UnnormalizedSamplerAddressMode) - -> Result, SamplerCreationError> - { + -> Result, SamplerCreationError> { let vk = device.pointers(); let border_color = address_u.border_color(); let border_color = match (border_color, address_v.border_color()) { - (Some(b1), Some(b2)) => { assert_eq!(b1, b2); Some(b1) }, + (Some(b1), Some(b2)) => { + assert_eq!(b1, b2); + Some(b1) + }, (None, b) => b, (b, None) => b, }; @@ -327,13 +384,13 @@ impl Sampler { let infos = vk::SamplerCreateInfo { sType: vk::STRUCTURE_TYPE_SAMPLER_CREATE_INFO, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved magFilter: filter as u32, minFilter: filter as u32, mipmapMode: vk::SAMPLER_MIPMAP_MODE_NEAREST, addressModeU: address_u.to_vk(), addressModeV: address_v.to_vk(), - addressModeW: vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // unused by the impl + addressModeW: vk::SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // unused by the impl mipLodBias: 0.0, anisotropyEnable: vk::FALSE, maxAnisotropy: 1.0, @@ -346,36 +403,38 @@ impl Sampler { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateSampler(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateSampler(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Sampler { - sampler: sampler, - device: device.clone(), - compare_mode: false, - unnormalized: true, - usable_with_float_formats: match border_color { - Some(BorderColor::FloatTransparentBlack) => true, - Some(BorderColor::FloatOpaqueBlack) => true, - Some(BorderColor::FloatOpaqueWhite) => true, - Some(_) => false, - None => true, - }, - usable_with_int_formats: match border_color { - Some(BorderColor::IntTransparentBlack) => true, - Some(BorderColor::IntOpaqueBlack) => true, - Some(BorderColor::IntOpaqueWhite) => true, - Some(_) => false, - None => true, - }, - usable_with_swizzling: match border_color { - Some(BorderColor::FloatOpaqueBlack) => false, - Some(BorderColor::IntOpaqueBlack) => false, - _ => true, - }, - })) + sampler: sampler, + device: device.clone(), + compare_mode: false, + unnormalized: true, + usable_with_float_formats: match border_color { + Some(BorderColor::FloatTransparentBlack) => true, + Some(BorderColor::FloatOpaqueBlack) => true, + Some(BorderColor::FloatOpaqueWhite) => true, + Some(_) => false, + None => true, + }, + usable_with_int_formats: match border_color { + Some(BorderColor::IntTransparentBlack) => true, + Some(BorderColor::IntOpaqueBlack) => true, + Some(BorderColor::IntOpaqueWhite) => true, + Some(_) => false, + None => true, + }, + usable_with_swizzling: match border_color { + Some(BorderColor::FloatOpaqueBlack) => false, + Some(BorderColor::IntOpaqueBlack) => false, + _ => true, + }, + })) } /// Returns true if the sampler is a compare-mode sampler. @@ -507,7 +566,7 @@ impl SamplerAddressMode { fn border_color(self) -> Option { match self { SamplerAddressMode::ClampToBorder(c) => Some(c), - _ => None + _ => None, } } } @@ -598,7 +657,7 @@ pub enum SamplerCreationError { /// The value that was requested. requested: f32, /// The maximum supported value. - maximum: f32 + maximum: f32, }, /// The requested mip lod bias exceeds the device's limits. @@ -606,7 +665,7 @@ pub enum SamplerCreationError { /// The value that was requested. requested: f32, /// The maximum supported value. - maximum: f32 + maximum: f32, }, /// Using `MirrorClampToEdge` requires enabling the `VK_KHR_sampler_mirror_clamp_to_edge` @@ -620,8 +679,8 @@ impl error::Error for SamplerCreationError { match *self { SamplerCreationError::OomError(_) => "not enough memory available", SamplerCreationError::TooManyObjects => "too many simultaneous sampler objects", - SamplerCreationError::SamplerAnisotropyFeatureNotEnabled => "the `sampler_anisotropy` \ - feature is not enabled", + SamplerCreationError::SamplerAnisotropyFeatureNotEnabled => + "the `sampler_anisotropy` feature is not enabled", SamplerCreationError::AnisotropyLimitExceeded { .. } => "anisotropy limit exceeded", SamplerCreationError::MipLodBiasLimitExceeded { .. } => "mip lod bias limit exceeded", SamplerCreationError::SamplerMirrorClampToEdgeExtensionNotEnabled => @@ -633,7 +692,7 @@ impl error::Error for SamplerCreationError { fn cause(&self) -> Option<&error::Error> { match *self { SamplerCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -659,7 +718,7 @@ impl From for SamplerCreationError { err @ Error::OutOfHostMemory => SamplerCreationError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => SamplerCreationError::OomError(OomError::from(err)), Error::TooManyObjects => SamplerCreationError::TooManyObjects, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -672,12 +731,18 @@ mod tests { fn create_regular() { let (device, queue) = gfx_dev_and_queue!(); - let s = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let s = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 1.0, - 0.0, 2.0).unwrap(); + sampler::SamplerAddressMode::Repeat, + 1.0, + 1.0, + 0.0, + 2.0) + .unwrap(); assert!(!s.compare_mode()); assert!(!s.is_unnormalized()); } @@ -686,12 +751,19 @@ mod tests { fn create_compare() { let (device, queue) = gfx_dev_and_queue!(); - let s = sampler::Sampler::compare(device, sampler::Filter::Linear, sampler::Filter::Linear, + let s = sampler::Sampler::compare(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 1.0, - 0.0, 2.0, sampler::Compare::Less).unwrap(); + sampler::SamplerAddressMode::Repeat, + 1.0, + 1.0, + 0.0, + 2.0, + sampler::Compare::Less) + .unwrap(); assert!(s.compare_mode()); assert!(!s.is_unnormalized()); @@ -701,10 +773,12 @@ mod tests { fn create_unnormalized() { let (device, queue) = gfx_dev_and_queue!(); - let s = sampler::Sampler::unnormalized(device, sampler::Filter::Linear, - sampler::UnnormalizedSamplerAddressMode::ClampToEdge, - sampler::UnnormalizedSamplerAddressMode::ClampToEdge) - .unwrap(); + let s = + sampler::Sampler::unnormalized(device, + sampler::Filter::Linear, + sampler::UnnormalizedSamplerAddressMode::ClampToEdge, + sampler::UnnormalizedSamplerAddressMode::ClampToEdge) + .unwrap(); assert!(!s.compare_mode()); assert!(s.is_unnormalized()); @@ -727,11 +801,17 @@ mod tests { fn min_lod_inferior() { let (device, queue) = gfx_dev_and_queue!(); - let _ = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let _ = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 1.0, 5.0, 2.0); + sampler::SamplerAddressMode::Repeat, + 1.0, + 1.0, + 5.0, + 2.0); } #[test] @@ -739,11 +819,17 @@ mod tests { fn max_anisotropy() { let (device, queue) = gfx_dev_and_queue!(); - let _ = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let _ = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 0.5, 0.0, 2.0); + sampler::SamplerAddressMode::Repeat, + 1.0, + 0.5, + 0.0, + 2.0); } #[test] @@ -754,26 +840,38 @@ mod tests { let b1 = sampler::BorderColor::IntTransparentBlack; let b2 = sampler::BorderColor::FloatOpaqueWhite; - let _ = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let _ = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::ClampToBorder(b1), sampler::SamplerAddressMode::ClampToBorder(b2), - sampler::SamplerAddressMode::Repeat, 1.0, 1.0, 5.0, 2.0); + sampler::SamplerAddressMode::Repeat, + 1.0, + 1.0, + 5.0, + 2.0); } #[test] fn anisotropy_feature() { let (device, queue) = gfx_dev_and_queue!(); - let r = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let r = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 2.0, 0.0, 2.0); + sampler::SamplerAddressMode::Repeat, + 1.0, + 2.0, + 0.0, + 2.0); match r { Err(sampler::SamplerCreationError::SamplerAnisotropyFeatureNotEnabled) => (), - _ => panic!() + _ => panic!(), } } @@ -781,16 +879,21 @@ mod tests { fn anisotropy_limit() { let (device, queue) = gfx_dev_and_queue!(sampler_anisotropy); - let r = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let r = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 1.0, 100000000.0, 0.0, + sampler::SamplerAddressMode::Repeat, + 1.0, + 100000000.0, + 0.0, 2.0); match r { Err(sampler::SamplerCreationError::AnisotropyLimitExceeded { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -798,16 +901,21 @@ mod tests { fn mip_lod_bias_limit() { let (device, queue) = gfx_dev_and_queue!(); - let r = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let r = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::Repeat, sampler::SamplerAddressMode::Repeat, - sampler::SamplerAddressMode::Repeat, 100000000.0, 1.0, 0.0, + sampler::SamplerAddressMode::Repeat, + 100000000.0, + 1.0, + 0.0, 2.0); match r { Err(sampler::SamplerCreationError::MipLodBiasLimitExceeded { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -815,16 +923,21 @@ mod tests { fn sampler_mirror_clamp_to_edge_extension() { let (device, queue) = gfx_dev_and_queue!(); - let r = sampler::Sampler::new(device, sampler::Filter::Linear, sampler::Filter::Linear, + let r = sampler::Sampler::new(device, + sampler::Filter::Linear, + sampler::Filter::Linear, sampler::MipmapMode::Nearest, sampler::SamplerAddressMode::MirrorClampToEdge, sampler::SamplerAddressMode::MirrorClampToEdge, - sampler::SamplerAddressMode::MirrorClampToEdge, 1.0, 1.0, - 0.0, 2.0); + sampler::SamplerAddressMode::MirrorClampToEdge, + 1.0, + 1.0, + 0.0, + 2.0); match r { Err(sampler::SamplerCreationError::SamplerMirrorClampToEdgeExtensionNotEnabled) => (), - _ => panic!() + _ => panic!(), } } } diff --git a/vulkano/src/swapchain/capabilities.rs b/vulkano/src/swapchain/capabilities.rs index 47620647..294e76f9 100644 --- a/vulkano/src/swapchain/capabilities.rs +++ b/vulkano/src/swapchain/capabilities.rs @@ -51,7 +51,7 @@ pub struct Capabilities { pub supported_usage_flags: ImageUsage, /// List of formats supported for the swapchain. - pub supported_formats: Vec<(Format, ColorSpace)>, // TODO: https://github.com/KhronosGroup/Vulkan-Docs/issues/207 + pub supported_formats: Vec<(Format, ColorSpace)>, // TODO: https://github.com/KhronosGroup/Vulkan-Docs/issues/207 /// List of present modes that are supported. `Fifo` is always guaranteed to be supported. pub present_modes: SupportedPresentModes, @@ -103,7 +103,7 @@ pub fn supported_present_modes_from_list(elem: I) -> SupportedPresentModes vk::PRESENT_MODE_MAILBOX_KHR => result.mailbox = true, vk::PRESENT_MODE_FIFO_KHR => result.fifo = true, vk::PRESENT_MODE_FIFO_RELAXED_KHR => result.relaxed = true, - _ => panic!("Wrong value for vk::PresentModeKHR") + _ => panic!("Wrong value for vk::PresentModeKHR"), } } result @@ -148,10 +148,22 @@ impl Iterator for SupportedPresentModesIter { #[inline] fn next(&mut self) -> Option { - if self.0.immediate { self.0.immediate = false; return Some(PresentMode::Immediate); } - if self.0.mailbox { self.0.mailbox = false; return Some(PresentMode::Mailbox); } - if self.0.fifo { self.0.fifo = false; return Some(PresentMode::Fifo); } - if self.0.relaxed { self.0.relaxed = false; return Some(PresentMode::Relaxed); } + if self.0.immediate { + self.0.immediate = false; + return Some(PresentMode::Immediate); + } + if self.0.mailbox { + self.0.mailbox = false; + return Some(PresentMode::Mailbox); + } + if self.0.fifo { + self.0.fifo = false; + return Some(PresentMode::Fifo); + } + if self.0.relaxed { + self.0.relaxed = false; + return Some(PresentMode::Relaxed); + } None } } @@ -214,10 +226,18 @@ pub struct SupportedCompositeAlpha { pub fn supported_composite_alpha_from_bits(val: u32) -> SupportedCompositeAlpha { let mut result = SupportedCompositeAlpha::none(); - if (val & vk::COMPOSITE_ALPHA_OPAQUE_BIT_KHR) != 0 { result.opaque = true; } - if (val & vk::COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) != 0 { result.pre_multiplied = true; } - if (val & vk::COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) != 0 { result.post_multiplied = true; } - if (val & vk::COMPOSITE_ALPHA_INHERIT_BIT_KHR) != 0 { result.inherit = true; } + if (val & vk::COMPOSITE_ALPHA_OPAQUE_BIT_KHR) != 0 { + result.opaque = true; + } + if (val & vk::COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) != 0 { + result.pre_multiplied = true; + } + if (val & vk::COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) != 0 { + result.post_multiplied = true; + } + if (val & vk::COMPOSITE_ALPHA_INHERIT_BIT_KHR) != 0 { + result.inherit = true; + } result } @@ -260,10 +280,22 @@ impl Iterator for SupportedCompositeAlphaIter { #[inline] fn next(&mut self) -> Option { - if self.0.opaque { self.0.opaque = false; return Some(CompositeAlpha::Opaque); } - if self.0.pre_multiplied { self.0.pre_multiplied = false; return Some(CompositeAlpha::PreMultiplied); } - if self.0.post_multiplied { self.0.post_multiplied = false; return Some(CompositeAlpha::PostMultiplied); } - if self.0.inherit { self.0.inherit = false; return Some(CompositeAlpha::Inherit); } + if self.0.opaque { + self.0.opaque = false; + return Some(CompositeAlpha::Opaque); + } + if self.0.pre_multiplied { + self.0.pre_multiplied = false; + return Some(CompositeAlpha::PreMultiplied); + } + if self.0.post_multiplied { + self.0.post_multiplied = false; + return Some(CompositeAlpha::PostMultiplied); + } + if self.0.inherit { + self.0.inherit = false; + return Some(CompositeAlpha::Inherit); + } None } } @@ -282,7 +314,8 @@ pub struct SupportedSurfaceTransforms { pub inherit: bool, } -pub fn surface_transforms_from_bits(val: vk::SurfaceTransformFlagsKHR) -> SupportedSurfaceTransforms { +pub fn surface_transforms_from_bits(val: vk::SurfaceTransformFlagsKHR) + -> SupportedSurfaceTransforms { macro_rules! v { ($val:expr, $out:ident, $e:expr, $f:ident) => ( if ($val & $e) != 0 { $out.$f = true; } @@ -290,17 +323,38 @@ pub fn surface_transforms_from_bits(val: vk::SurfaceTransformFlagsKHR) -> Suppor } let mut result = SupportedSurfaceTransforms::none(); - v!(val, result, vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, identity); - v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, rotate90); - v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, rotate180); - v!(val, result, vk::SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, rotate270); - v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, horizontal_mirror); - v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, - horizontal_mirror_rotate90); - v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, - horizontal_mirror_rotate180); - v!(val, result, vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, - horizontal_mirror_rotate270); + v!(val, + result, + vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + identity); + v!(val, + result, + vk::SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, + rotate90); + v!(val, + result, + vk::SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, + rotate180); + v!(val, + result, + vk::SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, + rotate270); + v!(val, + result, + vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, + horizontal_mirror); + v!(val, + result, + vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, + horizontal_mirror_rotate90); + v!(val, + result, + vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, + horizontal_mirror_rotate180); + v!(val, + result, + vk::SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, + horizontal_mirror_rotate270); v!(val, result, vk::SURFACE_TRANSFORM_INHERIT_BIT_KHR, inherit); result } @@ -354,15 +408,42 @@ impl Iterator for SupportedSurfaceTransformsIter { #[inline] fn next(&mut self) -> Option { - if self.0.identity { self.0.identity = false; return Some(SurfaceTransform::Identity); } - if self.0.rotate90 { self.0.rotate90 = false; return Some(SurfaceTransform::Rotate90); } - if self.0.rotate180 { self.0.rotate180 = false; return Some(SurfaceTransform::Rotate180); } - if self.0.rotate270 { self.0.rotate270 = false; return Some(SurfaceTransform::Rotate270); } - if self.0.horizontal_mirror { self.0.horizontal_mirror = false; return Some(SurfaceTransform::HorizontalMirror); } - if self.0.horizontal_mirror_rotate90 { self.0.horizontal_mirror_rotate90 = false; return Some(SurfaceTransform::HorizontalMirrorRotate90); } - if self.0.horizontal_mirror_rotate180 { self.0.horizontal_mirror_rotate180 = false; return Some(SurfaceTransform::HorizontalMirrorRotate180); } - if self.0.horizontal_mirror_rotate270 { self.0.horizontal_mirror_rotate270 = false; return Some(SurfaceTransform::HorizontalMirrorRotate270); } - if self.0.inherit { self.0.inherit = false; return Some(SurfaceTransform::Inherit); } + if self.0.identity { + self.0.identity = false; + return Some(SurfaceTransform::Identity); + } + if self.0.rotate90 { + self.0.rotate90 = false; + return Some(SurfaceTransform::Rotate90); + } + if self.0.rotate180 { + self.0.rotate180 = false; + return Some(SurfaceTransform::Rotate180); + } + if self.0.rotate270 { + self.0.rotate270 = false; + return Some(SurfaceTransform::Rotate270); + } + if self.0.horizontal_mirror { + self.0.horizontal_mirror = false; + return Some(SurfaceTransform::HorizontalMirror); + } + if self.0.horizontal_mirror_rotate90 { + self.0.horizontal_mirror_rotate90 = false; + return Some(SurfaceTransform::HorizontalMirrorRotate90); + } + if self.0.horizontal_mirror_rotate180 { + self.0.horizontal_mirror_rotate180 = false; + return Some(SurfaceTransform::HorizontalMirrorRotate180); + } + if self.0.horizontal_mirror_rotate270 { + self.0.horizontal_mirror_rotate270 = false; + return Some(SurfaceTransform::HorizontalMirrorRotate270); + } + if self.0.inherit { + self.0.inherit = false; + return Some(SurfaceTransform::Inherit); + } None } } @@ -497,6 +578,6 @@ pub fn color_space_from_num(val: u32) -> ColorSpace { vk::COLOR_SPACE_ADOBERGB_LINEAR_EXT => ColorSpace::AdobeRgbLinear, vk::COLOR_SPACE_ADOBERGB_NONLINEAR_EXT => ColorSpace::AdobeRgbNonLinear, vk::COLOR_SPACE_PASS_THROUGH_EXT => ColorSpace::PassThrough, - _ => panic!("Wrong value for color space enum") + _ => panic!("Wrong value for color space enum"), } } diff --git a/vulkano/src/swapchain/display.rs b/vulkano/src/swapchain/display.rs index 5267ab9b..49f54a67 100644 --- a/vulkano/src/swapchain/display.rs +++ b/vulkano/src/swapchain/display.rs @@ -8,13 +8,13 @@ // according to those terms. //! Allows you to create surfaces that fill a whole display, outside of the windowing system. -//! +//! //! **As far as the author knows, no existing device supports these features. Therefore the code //! here is mostly a draft and needs rework in both the API and the implementation.** -//! +//! //! The purpose of the objects in this module is to let you create a `Surface` object that //! represents a location on the screen. This is done in four steps: -//! +//! //! - Choose a `Display` where the surface will be located. A `Display` represents a display //! display, usually a monitor. The available displays can be enumerated with //! `Display::enumerate`. @@ -25,8 +25,8 @@ //! - Create a `Surface` object with `Surface::from_display_mode` and pass the chosen `DisplayMode` //! and `DisplayPlane`. -#![allow(dead_code)] // TODO: this module isn't finished -#![allow(unused_variables)] // TODO: this module isn't finished +#![allow(dead_code)] // TODO: this module isn't finished +#![allow(unused_variables)] // TODO: this module isn't finished use std::ffi::CStr; use std::ptr; @@ -35,12 +35,12 @@ use std::vec::IntoIter; use instance::Instance; use instance::PhysicalDevice; -use swapchain::capabilities; use swapchain::SupportedSurfaceTransforms; +use swapchain::capabilities; -use check_errors; use OomError; use VulkanObject; +use check_errors; use vk; // TODO: extract this to a `display` module and solve the visibility problems @@ -61,21 +61,22 @@ impl DisplayPlane { pub fn enumerate_raw(device: &PhysicalDevice) -> Result, OomError> { let vk = device.instance().pointers(); - assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead + assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead let num = unsafe { let mut num: u32 = 0; - try!(check_errors(vk.GetPhysicalDeviceDisplayPlanePropertiesKHR(device.internal_object(), - &mut num, ptr::null_mut()))); + check_errors(vk.GetPhysicalDeviceDisplayPlanePropertiesKHR(device.internal_object(), + &mut num, + ptr::null_mut()))?; num }; let planes: Vec = unsafe { let mut planes = Vec::with_capacity(num as usize); let mut num = num; - try!(check_errors(vk.GetPhysicalDeviceDisplayPlanePropertiesKHR(device.internal_object(), - &mut num, - planes.as_mut_ptr()))); + check_errors(vk.GetPhysicalDeviceDisplayPlanePropertiesKHR(device.internal_object(), + &mut num, + planes.as_mut_ptr()))?; planes.set_len(num as usize); planes }; @@ -107,7 +108,7 @@ impl DisplayPlane { } }).collect::>().into_iter()) } - + /// Enumerates all the display planes that are available on a given physical device. /// /// # Panic @@ -140,7 +141,10 @@ impl DisplayPlane { return false; } - self.supported_displays.iter().find(|&&d| d == display.internal_object()).is_some() + self.supported_displays + .iter() + .find(|&&d| d == display.internal_object()) + .is_some() } } @@ -150,41 +154,46 @@ impl DisplayPlane { pub struct Display { instance: Arc, physical_device: usize, - properties: Arc, // TODO: Arc because struct isn't clone + properties: Arc, // TODO: Arc because struct isn't clone } impl Display { /// See the docs of enumerate(). pub fn enumerate_raw(device: &PhysicalDevice) -> Result, OomError> { let vk = device.instance().pointers(); - assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead + assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead let num = unsafe { let mut num = 0; - try!(check_errors(vk.GetPhysicalDeviceDisplayPropertiesKHR(device.internal_object(), - &mut num, ptr::null_mut()))); + check_errors(vk.GetPhysicalDeviceDisplayPropertiesKHR(device.internal_object(), + &mut num, + ptr::null_mut()))?; num }; let displays: Vec = unsafe { let mut displays = Vec::with_capacity(num as usize); let mut num = num; - try!(check_errors(vk.GetPhysicalDeviceDisplayPropertiesKHR(device.internal_object(), - &mut num, - displays.as_mut_ptr()))); + check_errors(vk.GetPhysicalDeviceDisplayPropertiesKHR(device.internal_object(), + &mut num, + displays.as_mut_ptr()))?; displays.set_len(num as usize); displays }; - Ok(displays.into_iter().map(|prop| { - Display { - instance: device.instance().clone(), - physical_device: device.index(), - properties: Arc::new(prop), - } - }).collect::>().into_iter()) + Ok(displays + .into_iter() + .map(|prop| { + Display { + instance: device.instance().clone(), + physical_device: device.index(), + properties: Arc::new(prop), + } + }) + .collect::>() + .into_iter()) } - + /// Enumerates all the displays that are available on a given physical device. /// /// # Panic @@ -254,31 +263,37 @@ impl Display { let num = unsafe { let mut num = 0; - try!(check_errors(vk.GetDisplayModePropertiesKHR(self.physical_device().internal_object(), - self.properties.display, - &mut num, ptr::null_mut()))); + check_errors(vk.GetDisplayModePropertiesKHR(self.physical_device().internal_object(), + self.properties.display, + &mut num, + ptr::null_mut()))?; num }; let modes: Vec = unsafe { let mut modes = Vec::with_capacity(num as usize); let mut num = num; - try!(check_errors(vk.GetDisplayModePropertiesKHR(self.physical_device().internal_object(), - self.properties.display, &mut num, - modes.as_mut_ptr()))); + check_errors(vk.GetDisplayModePropertiesKHR(self.physical_device().internal_object(), + self.properties.display, + &mut num, + modes.as_mut_ptr()))?; modes.set_len(num as usize); modes }; - Ok(modes.into_iter().map(|mode| { - DisplayMode { - display: self.clone(), - display_mode: mode.displayMode, - parameters: mode.parameters, - } - }).collect::>().into_iter()) + Ok(modes + .into_iter() + .map(|mode| { + DisplayMode { + display: self.clone(), + display_mode: mode.displayMode, + parameters: mode.parameters, + } + }) + .collect::>() + .into_iter()) } - + /// Returns a list of all modes available on this display. /// /// # Panic diff --git a/vulkano/src/swapchain/mod.rs b/vulkano/src/swapchain/mod.rs index c2ed592f..a78b5d5c 100644 --- a/vulkano/src/swapchain/mod.rs +++ b/vulkano/src/swapchain/mod.rs @@ -8,9 +8,9 @@ // according to those terms. //! Link between Vulkan and a window and/or the screen. -//! +//! //! Before you can draw on the screen or a window, you have to create two objects: -//! +//! //! - Create a `Surface` object that represents the location where the image will show up (either //! a window or a monitor). //! - Create a `Swapchain` that uses that `Surface`. @@ -20,19 +20,19 @@ //! //! Once you have a swapchain, you can retrieve `Image` objects from it and draw to them just like //! you would draw on any other image. -//! +//! //! # Surfaces -//! +//! //! A surface is an object that represents a location where to render. It can be created from an //! instance and either a window handle (in a platform-specific way) or a monitor. -//! +//! //! In order to use surfaces, you will have to enable the `VK_KHR_surface` extension on the //! instance. See the `instance` module for more information about how to enable extensions. -//! +//! //! ## Creating a surface from a window -//! +//! //! There are 6 extensions that each allow you to create a surface from a type of window: -//! +//! //! - `VK_KHR_xlib_surface` //! - `VK_KHR_xcb_surface` //! - `VK_KHR_wayland_surface` @@ -48,7 +48,7 @@ //! error. //! //! **Note that the `Surface` object is unsafe**. It is your responsibility to keep the window -//! alive for at least as long as the surface exists. +//! alive for at least as long as the surface exists. //! //! ### Example //! @@ -78,9 +78,9 @@ //! Surface::from_hwnd(instance.clone(), hinstance, window).unwrap() //! }; //! ``` -//! +//! //! ## Creating a surface from a monitor -//! +//! //! Currently no system provides the `VK_KHR_display` extension that contains this feature. //! This feature is still a work-in-progress in vulkano and will reside in the `display` module. //! @@ -94,7 +94,7 @@ //! turn on the screen, one after another. More information below. //! //! Swapchains have several properties: -//! +//! //! - The number of images that will cycle on the screen. //! - The format of the images. //! - The 2D dimensions of the images, plus a number of layers, for a total of three dimensions. @@ -132,7 +132,7 @@ //! `acquire_next_image`. //! - Call `Swapchain::present` with the same index and by chaining the futures, in order to tell //! the implementation that you are finished drawing to the image and that it can queue a -//! command to present the image on the screen after the draw operations are finished. +//! command to present the image on the screen after the draw operations are finished. //! //! TODO: add example here //! loop { @@ -194,24 +194,24 @@ use std::sync::atomic::AtomicBool; pub use self::capabilities::Capabilities; -pub use self::capabilities::PresentMode; -pub use self::capabilities::SupportedPresentModes; -pub use self::capabilities::SupportedPresentModesIter; -pub use self::capabilities::SurfaceTransform; +pub use self::capabilities::ColorSpace; pub use self::capabilities::CompositeAlpha; +pub use self::capabilities::PresentMode; pub use self::capabilities::SupportedCompositeAlpha; pub use self::capabilities::SupportedCompositeAlphaIter; -pub use self::capabilities::ColorSpace; +pub use self::capabilities::SupportedPresentModes; +pub use self::capabilities::SupportedPresentModesIter; pub use self::capabilities::SupportedSurfaceTransforms; pub use self::capabilities::SupportedSurfaceTransformsIter; +pub use self::capabilities::SurfaceTransform; +pub use self::surface::CapabilitiesError; pub use self::surface::Surface; pub use self::surface::SurfaceCreationError; -pub use self::surface::CapabilitiesError; pub use self::swapchain::AcquireError; pub use self::swapchain::PresentFuture; pub use self::swapchain::Swapchain; -pub use self::swapchain::SwapchainCreationError; pub use self::swapchain::SwapchainAcquireFuture; +pub use self::swapchain::SwapchainCreationError; pub use self::swapchain::acquire_next_image; pub use self::swapchain::present; diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 52c6836e..2281c2d0 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -20,16 +20,16 @@ use image::ImageUsage; use instance::Instance; use instance::PhysicalDevice; use instance::QueueFamily; -use swapchain::capabilities; use swapchain::Capabilities; use swapchain::SurfaceSwapchainLock; +use swapchain::capabilities; use swapchain::display::DisplayMode; use swapchain::display::DisplayPlane; -use check_errors; use Error; use OomError; use VulkanObject; +use check_errors; use vk; /// Represents a surface on the screen. @@ -53,9 +53,14 @@ impl Surface { /// - Panics if `plane` doesn't support the display of `display_mode`. /// pub fn from_display_mode(display_mode: &DisplayMode, plane: &DisplayPlane) - -> Result, SurfaceCreationError> - { - if !display_mode.display().physical_device().instance().loaded_extensions().khr_display { + -> Result, SurfaceCreationError> { + if !display_mode + .display() + .physical_device() + .instance() + .loaded_extensions() + .khr_display + { return Err(SurfaceCreationError::MissingExtension { name: "VK_KHR_display" }); } @@ -70,30 +75,33 @@ impl Surface { let infos = vk::DisplaySurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved displayMode: display_mode.internal_object(), planeIndex: plane.index(), planeStackIndex: 0, // FIXME: plane.properties.currentStackIndex, - transform: vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, // TODO: let user choose - globalAlpha: 0.0, // TODO: let user choose - alphaMode: vk::DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, // TODO: let user choose - imageExtent: vk::Extent2D { // TODO: let user choose + transform: vk::SURFACE_TRANSFORM_IDENTITY_BIT_KHR, // TODO: let user choose + globalAlpha: 0.0, // TODO: let user choose + alphaMode: vk::DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, // TODO: let user choose + imageExtent: vk::Extent2D { + // TODO: let user choose width: display_mode.visible_region()[0], height: display_mode.visible_region()[1], }, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateDisplayPlaneSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateDisplayPlaneSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from a Win32 window. @@ -105,8 +113,7 @@ impl Surface { /// The caller must ensure that the `hinstance` and the `hwnd` are both correct and stay /// alive for the entire lifetime of the surface. pub unsafe fn from_hwnd(instance: Arc, hinstance: *const T, hwnd: *const U) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_win32_surface { @@ -117,22 +124,24 @@ impl Surface { let infos = vk::Win32SurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved hinstance: hinstance as *mut _, hwnd: hwnd as *mut _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateWin32SurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateWin32SurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from an XCB window. @@ -144,8 +153,7 @@ impl Surface { /// The caller must ensure that the `connection` and the `window` are both correct and stay /// alive for the entire lifetime of the surface. pub unsafe fn from_xcb(instance: Arc, connection: *const C, window: u32) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_xcb_surface { @@ -153,25 +161,27 @@ impl Surface { } let surface = { - let infos = vk::XcbSurfaceCreateInfoKHR { + let infos = vk::XcbSurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved connection: connection as *mut _, window: window, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateXcbSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateXcbSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from an Xlib window. @@ -183,8 +193,7 @@ impl Surface { /// The caller must ensure that the `display` and the `window` are both correct and stay /// alive for the entire lifetime of the surface. pub unsafe fn from_xlib(instance: Arc, display: *const D, window: c_ulong) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_xlib_surface { @@ -192,25 +201,27 @@ impl Surface { } let surface = { - let infos = vk::XlibSurfaceCreateInfoKHR { + let infos = vk::XlibSurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved dpy: display as *mut _, window: window, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateXlibSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateXlibSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from a Wayland window. @@ -221,9 +232,9 @@ impl Surface { /// /// The caller must ensure that the `display` and the `surface` are both correct and stay /// alive for the entire lifetime of the surface. - pub unsafe fn from_wayland(instance: Arc, display: *const D, surface: *const S) - -> Result, SurfaceCreationError> - { + pub unsafe fn from_wayland(instance: Arc, display: *const D, + surface: *const S) + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_wayland_surface { @@ -234,22 +245,24 @@ impl Surface { let infos = vk::WaylandSurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved display: display as *mut _, surface: surface as *mut _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateWaylandSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateWaylandSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from a MIR window. @@ -262,8 +275,7 @@ impl Surface { /// The caller must ensure that the `connection` and the `surface` are both correct and stay /// alive for the entire lifetime of the surface. pub unsafe fn from_mir(instance: Arc, connection: *const C, surface: *const S) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_mir_surface { @@ -271,25 +283,27 @@ impl Surface { } let surface = { - let infos = vk::MirSurfaceCreateInfoKHR { + let infos = vk::MirSurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved connection: connection as *mut _, mirSurface: surface as *mut _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateMirSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateMirSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from an Android window. @@ -299,8 +313,7 @@ impl Surface { /// The caller must ensure that the `window` is correct and stays alive for the entire /// lifetime of the surface. pub unsafe fn from_anativewindow(instance: Arc, window: *const T) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().khr_android_surface { @@ -311,21 +324,23 @@ impl Surface { let infos = vk::AndroidSurfaceCreateInfoKHR { sType: vk::STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved window: window as *mut _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateAndroidSurfaceKHR(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateAndroidSurfaceKHR(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from an iOS `UIView`. @@ -336,8 +351,7 @@ impl Surface { /// lifetime of the surface. /// - The `UIView` must be backed by a `CALayer` instance of type `CAMetalLayer`. pub unsafe fn from_ios_moltenvk(instance: Arc, view: *const T) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().mvk_ios_surface { @@ -348,21 +362,23 @@ impl Surface { let infos = vk::IOSSurfaceCreateInfoMVK { sType: vk::STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved pView: view as *const _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateIOSSurfaceMVK(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateIOSSurfaceMVK(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from a MacOS `NSView`. @@ -373,8 +389,7 @@ impl Surface { /// lifetime of the surface. /// - The `NSView` must be backed by a `CALayer` instance of type `CAMetalLayer`. pub unsafe fn from_macos_moltenvk(instance: Arc, view: *const T) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().mvk_macos_surface { @@ -385,21 +400,23 @@ impl Surface { let infos = vk::MacOSSurfaceCreateInfoMVK { sType: vk::STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved pView: view as *const _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateMacOSSurfaceMVK(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateMacOSSurfaceMVK(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Creates a `Surface` from a `code:nn::code:vi::code:Layer`. @@ -409,8 +426,7 @@ impl Surface { /// The caller must ensure that the `window` is correct and stays alive for the entire /// lifetime of the surface. pub unsafe fn from_vi_surface(instance: Arc, window: *const T) - -> Result, SurfaceCreationError> - { + -> Result, SurfaceCreationError> { let vk = instance.pointers(); if !instance.loaded_extensions().nn_vi_surface { @@ -421,21 +437,23 @@ impl Surface { let infos = vk::ViSurfaceCreateInfoNN { sType: vk::STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved window: window as *mut _, }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateViSurfaceNN(instance.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateViSurfaceNN(instance.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Arc::new(Surface { - instance: instance.clone(), - surface: surface, - has_swapchain: AtomicBool::new(false), - })) + instance: instance.clone(), + surface: surface, + has_swapchain: AtomicBool::new(false), + })) } /// Returns true if the given queue family can draw on this surface. @@ -445,10 +463,12 @@ impl Surface { let vk = self.instance.pointers(); let mut output = mem::uninitialized(); - try!(check_errors( - vk.GetPhysicalDeviceSurfaceSupportKHR(queue.physical_device().internal_object(), - queue.id(), self.surface, &mut output) - )); + check_errors(vk.GetPhysicalDeviceSurfaceSupportKHR(queue + .physical_device() + .internal_object(), + queue.id(), + self.surface, + &mut output))?; Ok(output != 0) } } @@ -467,54 +487,53 @@ impl Surface { /// pub fn capabilities(&self, device: PhysicalDevice) -> Result { unsafe { - assert_eq!(&*self.instance as *const _, &**device.instance() as *const _, + assert_eq!(&*self.instance as *const _, + &**device.instance() as *const _, "Instance mismatch in Surface::capabilities"); let vk = self.instance.pointers(); let caps = { let mut out: vk::SurfaceCapabilitiesKHR = mem::uninitialized(); - try!(check_errors( - vk.GetPhysicalDeviceSurfaceCapabilitiesKHR(device.internal_object(), - self.surface, &mut out) - )); + check_errors(vk.GetPhysicalDeviceSurfaceCapabilitiesKHR(device.internal_object(), + self.surface, + &mut out))?; out }; let formats = { let mut num = 0; - try!(check_errors( - vk.GetPhysicalDeviceSurfaceFormatsKHR(device.internal_object(), - self.surface, &mut num, - ptr::null_mut()) - )); + check_errors(vk.GetPhysicalDeviceSurfaceFormatsKHR(device.internal_object(), + self.surface, + &mut num, + ptr::null_mut()))?; let mut formats = Vec::with_capacity(num as usize); - try!(check_errors( - vk.GetPhysicalDeviceSurfaceFormatsKHR(device.internal_object(), - self.surface, &mut num, - formats.as_mut_ptr()) - )); + check_errors(vk.GetPhysicalDeviceSurfaceFormatsKHR(device.internal_object(), + self.surface, + &mut num, + formats.as_mut_ptr()))?; formats.set_len(num as usize); formats }; let modes = { let mut num = 0; - try!(check_errors( - vk.GetPhysicalDeviceSurfacePresentModesKHR(device.internal_object(), - self.surface, &mut num, - ptr::null_mut()) - )); + check_errors(vk.GetPhysicalDeviceSurfacePresentModesKHR(device.internal_object(), + self.surface, + &mut num, + ptr::null_mut()))?; let mut modes = Vec::with_capacity(num as usize); - try!(check_errors( - vk.GetPhysicalDeviceSurfacePresentModesKHR(device.internal_object(), - self.surface, &mut num, - modes.as_mut_ptr()) - )); + check_errors(vk.GetPhysicalDeviceSurfacePresentModesKHR(device.internal_object(), + self.surface, + &mut num, + modes.as_mut_ptr()))?; modes.set_len(num as usize); - debug_assert!(modes.iter().find(|&&m| m == vk::PRESENT_MODE_FIFO_KHR).is_some()); + debug_assert!(modes + .iter() + .find(|&&m| m == vk::PRESENT_MODE_FIFO_KHR) + .is_some()); debug_assert!(modes.iter().count() > 0); capabilities::supported_present_modes_from_list(modes.into_iter()) }; @@ -598,7 +617,7 @@ pub enum SurfaceCreationError { /// The extension required for this function was not enabled. MissingExtension { /// Name of the missing extension. - name: &'static str + name: &'static str, }, } @@ -607,8 +626,8 @@ impl error::Error for SurfaceCreationError { fn description(&self) -> &str { match *self { SurfaceCreationError::OomError(_) => "not enough memory available", - SurfaceCreationError::MissingExtension { .. } => "the extension required for this \ - function was not enabled", + SurfaceCreationError::MissingExtension { .. } => + "the extension required for this function was not enabled", } } @@ -616,7 +635,7 @@ impl error::Error for SurfaceCreationError { fn cause(&self) -> Option<&error::Error> { match *self { SurfaceCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -641,7 +660,7 @@ impl From for SurfaceCreationError { match err { err @ Error::OutOfHostMemory => SurfaceCreationError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => SurfaceCreationError::OomError(OomError::from(err)), - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -670,7 +689,7 @@ impl error::Error for CapabilitiesError { fn cause(&self) -> Option<&error::Error> { match *self { CapabilitiesError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -696,7 +715,7 @@ impl From for CapabilitiesError { err @ Error::OutOfHostMemory => CapabilitiesError::OomError(OomError::from(err)), err @ Error::OutOfDeviceMemory => CapabilitiesError::OomError(OomError::from(err)), Error::SurfaceLost => CapabilitiesError::SurfaceLost, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -712,7 +731,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_hwnd(instance, ptr::null::(), ptr::null::()) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -721,7 +740,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_xcb(instance, ptr::null::(), 0) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -730,7 +749,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_xlib(instance, ptr::null::(), 0) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -739,7 +758,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_wayland(instance, ptr::null::(), ptr::null::()) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -748,7 +767,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_mir(instance, ptr::null::(), ptr::null::()) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } @@ -757,7 +776,7 @@ mod tests { let instance = instance!(); match unsafe { Surface::from_anativewindow(instance, ptr::null::()) } { Err(SurfaceCreationError::MissingExtension { .. }) => (), - _ => panic!() + _ => panic!(), } } } diff --git a/vulkano/src/swapchain/swapchain.rs b/vulkano/src/swapchain/swapchain.rs index b6bcd66a..e13f5a55 100644 --- a/vulkano/src/swapchain/swapchain.rs +++ b/vulkano/src/swapchain/swapchain.rs @@ -30,15 +30,15 @@ use image::ImageAccess; use image::ImageDimensions; use image::ImageLayout; use image::ImageUsage; -use image::sys::UnsafeImage; use image::swapchain::SwapchainImage; +use image::sys::UnsafeImage; use swapchain::CapabilitiesError; use swapchain::ColorSpace; use swapchain::CompositeAlpha; use swapchain::PresentMode; use swapchain::Surface; -use swapchain::SurfaceTransform; use swapchain::SurfaceSwapchainLock; +use swapchain::SurfaceTransform; use sync::AccessCheckError; use sync::AccessError; use sync::AccessFlagBits; @@ -48,11 +48,11 @@ use sync::PipelineStages; use sync::Semaphore; use sync::SharingMode; -use check_errors; use Error; use OomError; use Success; use VulkanObject; +use check_errors; use vk; /// Tries to take ownership of an image in order to draw on it. @@ -66,8 +66,7 @@ use vk; // TODO: has to make sure vkQueuePresent is called, because calling acquire_next_image many // times in a row is an error pub fn acquire_next_image(swapchain: Arc, timeout: Option) - -> Result<(usize, SwapchainAcquireFuture), AcquireError> -{ + -> Result<(usize, SwapchainAcquireFuture), AcquireError> { unsafe { // Check that this is not an old swapchain. From specs: // > swapchain must not have been replaced by being passed as the @@ -79,35 +78,40 @@ pub fn acquire_next_image(swapchain: Arc, timeout: Option) let vk = swapchain.device.pointers(); - let semaphore = try!(Semaphore::new(swapchain.device.clone())); + let semaphore = Semaphore::new(swapchain.device.clone())?; let timeout_ns = if let Some(timeout) = timeout { - timeout.as_secs().saturating_mul(1_000_000_000) - .saturating_add(timeout.subsec_nanos() as u64) + timeout + .as_secs() + .saturating_mul(1_000_000_000) + .saturating_add(timeout.subsec_nanos() as u64) } else { u64::max_value() }; let mut out = mem::uninitialized(); - let r = try!(check_errors(vk.AcquireNextImageKHR(swapchain.device.internal_object(), - swapchain.swapchain, timeout_ns, - semaphore.internal_object(), 0, - &mut out))); + let r = check_errors(vk.AcquireNextImageKHR(swapchain.device.internal_object(), + swapchain.swapchain, + timeout_ns, + semaphore.internal_object(), + 0, + &mut out))?; let id = match r { Success::Success => out as usize, Success::Suboptimal => out as usize, // TODO: give that info to the user Success::NotReady => return Err(AcquireError::Timeout), Success::Timeout => return Err(AcquireError::Timeout), - s => panic!("unexpected success value: {:?}", s) + s => panic!("unexpected success value: {:?}", s), }; - Ok((id, SwapchainAcquireFuture { - swapchain: swapchain.clone(), // TODO: don't clone - semaphore: semaphore, - image_id: id, - finished: AtomicBool::new(false), - })) + Ok((id, + SwapchainAcquireFuture { + swapchain: swapchain.clone(), // TODO: don't clone + semaphore: semaphore, + image_id: id, + finished: AtomicBool::new(false), + })) } } @@ -185,9 +189,9 @@ impl Swapchain { /// /// See also the `Surface::get_capabilities` function which returns the values that are /// supported by the implementation. All the parameters that you pass to `Swapchain::new` - /// must be supported. + /// must be supported. /// - /// The `clipped` parameter indicates whether the implementation is allowed to discard + /// The `clipped` parameter indicates whether the implementation is allowed to discard /// rendering operations that affect regions of the surface which aren't visible. This is /// important to take into account if your fragment shader has side-effects or if you want to /// read back the content of the image afterwards. @@ -205,35 +209,56 @@ impl Swapchain { // TODO: add `ColorSpace` parameter // TODO: isn't it unsafe to take the surface through an Arc when it comes to vulkano-win? #[inline] - pub fn new(device: Arc, surface: Arc, num_images: u32, format: F, - dimensions: [u32; 2], layers: u32, usage: ImageUsage, sharing: S, - transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode, - clipped: bool, old_swapchain: Option<&Arc>) - -> Result<(Arc, Vec>), SwapchainCreationError> - where F: FormatDesc, S: Into + pub fn new( + device: Arc, surface: Arc, num_images: u32, format: F, + dimensions: [u32; 2], layers: u32, usage: ImageUsage, sharing: S, + transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode, clipped: bool, + old_swapchain: Option<&Arc>) + -> Result<(Arc, Vec>), SwapchainCreationError> + where F: FormatDesc, + S: Into { - Swapchain::new_inner(device, surface, num_images, format.format(), - ColorSpace::SrgbNonLinear, dimensions, layers, usage, sharing.into(), - transform, alpha, mode, clipped, old_swapchain.map(|s| &**s)) + Swapchain::new_inner(device, + surface, + num_images, + format.format(), + ColorSpace::SrgbNonLinear, + dimensions, + layers, + usage, + sharing.into(), + transform, + alpha, + mode, + clipped, + old_swapchain.map(|s| &**s)) } - /// Recreates the swapchain with new dimensions. - pub fn recreate_with_dimension(&self, dimensions: [u32; 2]) - -> Result<(Arc, Vec>), - SwapchainCreationError> - { - Swapchain::new_inner(self.device.clone(), self.surface.clone(), self.num_images, - self.format, self.color_space, dimensions, self.layers, self.usage, - self.sharing.clone(), self.transform, self.alpha, self.mode, - self.clipped, Some(self)) + /// Recreates the swapchain with new dimensions. + pub fn recreate_with_dimension( + &self, dimensions: [u32; 2]) + -> Result<(Arc, Vec>), SwapchainCreationError> { + Swapchain::new_inner(self.device.clone(), + self.surface.clone(), + self.num_images, + self.format, + self.color_space, + dimensions, + self.layers, + self.usage, + self.sharing.clone(), + self.transform, + self.alpha, + self.mode, + self.clipped, + Some(self)) } fn new_inner(device: Arc, surface: Arc, num_images: u32, format: Format, color_space: ColorSpace, dimensions: [u32; 2], layers: u32, usage: ImageUsage, sharing: SharingMode, transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode, clipped: bool, old_swapchain: Option<&Swapchain>) - -> Result<(Arc, Vec>), SwapchainCreationError> - { + -> Result<(Arc, Vec>), SwapchainCreationError> { assert_eq!(device.instance().internal_object(), surface.instance().internal_object()); @@ -247,7 +272,11 @@ impl Swapchain { return Err(SwapchainCreationError::UnsupportedMaxImagesCount); } } - if !capabilities.supported_formats.iter().any(|&(f, c)| f == format && c == color_space) { + if !capabilities + .supported_formats + .iter() + .any(|&(f, c)| f == format && c == color_space) + { return Err(SwapchainCreationError::UnsupportedFormat); } if dimensions[0] < capabilities.min_image_extent[0] { @@ -265,7 +294,9 @@ impl Swapchain { if layers < 1 && layers > capabilities.max_image_array_layers { return Err(SwapchainCreationError::UnsupportedArrayLayers); } - if (usage.to_usage_bits() & capabilities.supported_usage_flags.to_usage_bits()) != usage.to_usage_bits() { + if (usage.to_usage_bits() & capabilities.supported_usage_flags.to_usage_bits()) != + usage.to_usage_bits() + { return Err(SwapchainCreationError::UnsupportedUsageFlags); } if !capabilities.supported_transforms.supports(transform) { @@ -282,13 +313,15 @@ impl Swapchain { if let Some(sc) = old_swapchain { if surface.internal_object() != sc.surface.internal_object() { return Err(SwapchainCreationError::OldSwapchainSurfaceMismatch); - } + } } // Checking that the surface doesn't already have a swapchain. if old_swapchain.is_none() { let has_already = surface.flag().swap(true, Ordering::AcqRel); - if has_already { return Err(SwapchainCreationError::SurfaceInUse); } + if has_already { + return Err(SwapchainCreationError::SurfaceInUse); + } } if !device.loaded_extensions().khr_swapchain { @@ -307,19 +340,23 @@ impl Swapchain { let swapchain = unsafe { let (sh_mode, sh_count, sh_indices) = match sharing { SharingMode::Exclusive(_) => (vk::SHARING_MODE_EXCLUSIVE, 0, ptr::null()), - SharingMode::Concurrent(ref ids) => (vk::SHARING_MODE_CONCURRENT, ids.len() as u32, + SharingMode::Concurrent(ref ids) => (vk::SHARING_MODE_CONCURRENT, + ids.len() as u32, ids.as_ptr()), }; let infos = vk::SwapchainCreateInfoKHR { sType: vk::STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, pNext: ptr::null(), - flags: 0, // reserved + flags: 0, // reserved surface: surface.internal_object(), minImageCount: num_images, imageFormat: format as u32, imageColorSpace: color_space as u32, - imageExtent: vk::Extent2D { width: dimensions[0], height: dimensions[1] }, + imageExtent: vk::Extent2D { + width: dimensions[0], + height: dimensions[1], + }, imageArrayLayers: layers, imageUsage: usage.to_usage_bits(), imageSharingMode: sh_mode, @@ -337,60 +374,73 @@ impl Swapchain { }; let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateSwapchainKHR(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateSwapchainKHR(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; let image_handles = unsafe { let mut num = 0; - try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(), - swapchain, &mut num, - ptr::null_mut()))); + check_errors(vk.GetSwapchainImagesKHR(device.internal_object(), + swapchain, + &mut num, + ptr::null_mut()))?; let mut images = Vec::with_capacity(num as usize); - try!(check_errors(vk.GetSwapchainImagesKHR(device.internal_object(), - swapchain, &mut num, - images.as_mut_ptr()))); + check_errors(vk.GetSwapchainImagesKHR(device.internal_object(), + swapchain, + &mut num, + images.as_mut_ptr()))?; images.set_len(num as usize); images }; - let images = image_handles.into_iter().enumerate().map(|(id, image)| unsafe { - let dims = ImageDimensions::Dim2d { - width: dimensions[0], - height: dimensions[1], - array_layers: layers, - cubemap_compatible: false, - }; + let images = image_handles + .into_iter() + .enumerate() + .map(|(id, image)| unsafe { + let dims = ImageDimensions::Dim2d { + width: dimensions[0], + height: dimensions[1], + array_layers: layers, + cubemap_compatible: false, + }; - let img = UnsafeImage::from_raw(device.clone(), image, usage.to_usage_bits(), format, - dims, 1, 1); + let img = UnsafeImage::from_raw(device.clone(), + image, + usage.to_usage_bits(), + format, + dims, + 1, + 1); - ImageEntry { - image: img, - undefined_layout: AtomicBool::new(true) - } - }).collect::>(); + ImageEntry { + image: img, + undefined_layout: AtomicBool::new(true), + } + }) + .collect::>(); let swapchain = Arc::new(Swapchain { - device: device.clone(), - surface: surface.clone(), - swapchain: swapchain, - images: images, - stale: Mutex::new(false), - num_images: num_images, - format: format, - color_space: color_space, - dimensions: dimensions, - layers: layers, - usage: usage.clone(), - sharing: sharing, - transform: transform, - alpha: alpha, - mode: mode, - clipped: clipped, - }); + device: device.clone(), + surface: surface.clone(), + swapchain: swapchain, + images: images, + stale: Mutex::new(false), + num_images: num_images, + format: format, + color_space: color_space, + dimensions: dimensions, + layers: layers, + usage: usage.clone(), + sharing: sharing, + transform: transform, + alpha: alpha, + mode: mode, + clipped: clipped, + }); let swapchain_images = unsafe { let mut swapchain_images = Vec::with_capacity(swapchain.images.len()); @@ -411,7 +461,7 @@ impl Swapchain { /// Returns the number of images of the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn num_images(&self) -> u32 { self.images.len() as u32 @@ -419,7 +469,7 @@ impl Swapchain { /// Returns the format of the images of the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn format(&self) -> Format { self.format @@ -427,7 +477,7 @@ impl Swapchain { /// Returns the dimensions of the images of the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn dimensions(&self) -> [u32; 2] { self.dimensions @@ -435,7 +485,7 @@ impl Swapchain { /// Returns the number of layers of the images of the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn layers(&self) -> u32 { self.layers @@ -443,7 +493,7 @@ impl Swapchain { /// Returns the transform that was passed when creating the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn transform(&self) -> SurfaceTransform { self.transform @@ -451,7 +501,7 @@ impl Swapchain { /// Returns the alpha mode that was passed when creating the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn composite_alpha(&self) -> CompositeAlpha { self.alpha @@ -459,7 +509,7 @@ impl Swapchain { /// Returns the present mode that was passed when creating the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn present_mode(&self) -> PresentMode { self.mode @@ -467,7 +517,7 @@ impl Swapchain { /// Returns the value of `clipped` that was passed when creating the swapchain. /// - /// See the documentation of `Swapchain::new`. + /// See the documentation of `Swapchain::new`. #[inline] pub fn clipped(&self) -> bool { self.clipped @@ -597,7 +647,7 @@ impl error::Error for SwapchainCreationError { fn cause(&self) -> Option<&error::Error> { match *self { SwapchainCreationError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -628,7 +678,7 @@ impl From for SwapchainCreationError { err @ Error::NativeWindowInUse => { SwapchainCreationError::NativeWindowInUse }, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } @@ -706,34 +756,35 @@ unsafe impl GpuFuture for SwapchainAcquireFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { Err(AccessCheckError::Unknown) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { let swapchain_image = self.swapchain.raw_image(self.image_id).unwrap(); if swapchain_image.internal_object() != image.inner().internal_object() { return Err(AccessCheckError::Unknown); } - if self.swapchain.images[self.image_id].undefined_layout.load(Ordering::Relaxed) && - layout != ImageLayout::Undefined + if self.swapchain.images[self.image_id] + .undefined_layout + .load(Ordering::Relaxed) && layout != ImageLayout::Undefined { return Err(AccessCheckError::Denied(AccessError::ImageNotInitialized { - requested: layout - })); + requested: layout, + })); } if layout != ImageLayout::Undefined && layout != ImageLayout::PresentSrc { return Err(AccessCheckError::Denied(AccessError::UnexpectedImageLayout { - allowed: ImageLayout::PresentSrc, - requested: layout, - })); + allowed: ImageLayout::PresentSrc, + requested: layout, + })); } Ok(None) @@ -750,7 +801,7 @@ unsafe impl DeviceOwned for SwapchainAcquireFuture { impl Drop for SwapchainAcquireFuture { fn drop(&mut self) { if !*self.finished.get_mut() { - panic!() // FIXME: what to do? + panic!() // FIXME: what to do? /*// TODO: handle errors? let fence = Fence::new(self.device().clone()).unwrap(); let mut builder = SubmitCommandBufferBuilder::new(); @@ -799,7 +850,7 @@ impl error::Error for AcquireError { fn cause(&self) -> Option<&error::Error> { match *self { AcquireError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -827,14 +878,16 @@ impl From for AcquireError { Error::DeviceLost => AcquireError::DeviceLost, Error::SurfaceLost => AcquireError::SurfaceLost, Error::OutOfDate => AcquireError::OutOfDate, - _ => panic!("unexpected error: {:?}", err) + _ => panic!("unexpected error: {:?}", err), } } } /// Represents a swapchain image being presented on the screen. #[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"] -pub struct PresentFuture

where P: GpuFuture { +pub struct PresentFuture

+ where P: GpuFuture +{ previous: P, queue: Arc, swapchain: Arc, @@ -847,7 +900,9 @@ pub struct PresentFuture

where P: GpuFuture { finished: AtomicBool, } -impl

PresentFuture

where P: GpuFuture { +impl

PresentFuture

+ where P: GpuFuture +{ /// Returns the index of the image in the list of images returned when creating the swapchain. #[inline] pub fn image_id(&self) -> usize { @@ -861,7 +916,9 @@ impl

PresentFuture

where P: GpuFuture { } } -unsafe impl

GpuFuture for PresentFuture

where P: GpuFuture { +unsafe impl

GpuFuture for PresentFuture

+ where P: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { self.previous.cleanup_finished(); @@ -878,37 +935,37 @@ unsafe impl

GpuFuture for PresentFuture

where P: GpuFuture { // TODO: if the swapchain image layout is not PRESENT, should add a transition command // buffer - Ok(match try!(self.previous.build_submission()) { - SubmitAnyBuilder::Empty => { - let mut builder = SubmitPresentBuilder::new(); - builder.add_swapchain(&self.swapchain, self.image_id as u32); - SubmitAnyBuilder::QueuePresent(builder) - }, - SubmitAnyBuilder::SemaphoresWait(sem) => { - let mut builder: SubmitPresentBuilder = sem.into(); - builder.add_swapchain(&self.swapchain, self.image_id as u32); - SubmitAnyBuilder::QueuePresent(builder) - }, - SubmitAnyBuilder::CommandBuffer(cb) => { - try!(cb.submit(&queue.unwrap())); // FIXME: wrong because build_submission can be called multiple times - let mut builder = SubmitPresentBuilder::new(); - builder.add_swapchain(&self.swapchain, self.image_id as u32); - SubmitAnyBuilder::QueuePresent(builder) - }, - SubmitAnyBuilder::BindSparse(cb) => { - try!(cb.submit(&queue.unwrap())); // FIXME: wrong because build_submission can be called multiple times - let mut builder = SubmitPresentBuilder::new(); - builder.add_swapchain(&self.swapchain, self.image_id as u32); - SubmitAnyBuilder::QueuePresent(builder) - }, - SubmitAnyBuilder::QueuePresent(present) => { - unimplemented!() // TODO: + Ok(match self.previous.build_submission()? { + SubmitAnyBuilder::Empty => { + let mut builder = SubmitPresentBuilder::new(); + builder.add_swapchain(&self.swapchain, self.image_id as u32); + SubmitAnyBuilder::QueuePresent(builder) + }, + SubmitAnyBuilder::SemaphoresWait(sem) => { + let mut builder: SubmitPresentBuilder = sem.into(); + builder.add_swapchain(&self.swapchain, self.image_id as u32); + SubmitAnyBuilder::QueuePresent(builder) + }, + SubmitAnyBuilder::CommandBuffer(cb) => { + cb.submit(&queue.unwrap())?; // FIXME: wrong because build_submission can be called multiple times + let mut builder = SubmitPresentBuilder::new(); + builder.add_swapchain(&self.swapchain, self.image_id as u32); + SubmitAnyBuilder::QueuePresent(builder) + }, + SubmitAnyBuilder::BindSparse(cb) => { + cb.submit(&queue.unwrap())?; // FIXME: wrong because build_submission can be called multiple times + let mut builder = SubmitPresentBuilder::new(); + builder.add_swapchain(&self.swapchain, self.image_id as u32); + SubmitAnyBuilder::QueuePresent(builder) + }, + SubmitAnyBuilder::QueuePresent(present) => { + unimplemented!() // TODO: /*present.submit(); let mut builder = SubmitPresentBuilder::new(); builder.add_swapchain(self.command_buffer.inner(), self.image_id); SubmitAnyBuilder::CommandBuffer(builder)*/ - }, - }) + }, + }) } #[inline] @@ -917,11 +974,11 @@ unsafe impl

GpuFuture for PresentFuture

where P: GpuFuture { // If `flushed` already contains `true`, then `build_submission` will return `Empty`. match self.build_submission()? { - SubmitAnyBuilder::Empty => {} + SubmitAnyBuilder::Empty => {}, SubmitAnyBuilder::QueuePresent(present) => { present.submit(&self.queue)?; - } - _ => unreachable!() + }, + _ => unreachable!(), } self.flushed.store(true, Ordering::SeqCst); @@ -944,45 +1001,50 @@ unsafe impl

GpuFuture for PresentFuture

where P: GpuFuture { #[inline] fn queue(&self) -> Option> { debug_assert!(match self.previous.queue() { - None => true, - Some(q) => q.is_same(&self.queue) - }); + None => true, + Some(q) => q.is_same(&self.queue), + }); Some(self.queue.clone()) } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { self.previous.check_buffer_access(buffer, exclusive, queue) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { let swapchain_image = self.swapchain.raw_image(self.image_id).unwrap(); if swapchain_image.internal_object() == image.inner().internal_object() { - // This future presents the swapchain image, which "unlocks" it. Therefore any attempt + // This future presents the swapchain image, which "unlocks" it. Therefore any attempt // to use this swapchain image afterwards shouldn't get granted automatic access. // Instead any attempt to access the image afterwards should get an authorization from // a later swapchain acquire future. Hence why we return `Unknown` here. Err(AccessCheckError::Unknown) } else { - self.previous.check_image_access(image, layout, exclusive, queue) + self.previous + .check_image_access(image, layout, exclusive, queue) } } } -unsafe impl

DeviceOwned for PresentFuture

where P: GpuFuture { +unsafe impl

DeviceOwned for PresentFuture

+ where P: GpuFuture +{ #[inline] fn device(&self) -> &Arc { self.queue.device() } } -impl

Drop for PresentFuture

where P: GpuFuture { +impl

Drop for PresentFuture

+ where P: GpuFuture +{ fn drop(&mut self) { unsafe { if !*self.finished.get_mut() { diff --git a/vulkano/src/sync/event.rs b/vulkano/src/sync/event.rs index 9d6760bd..3cea5ac1 100644 --- a/vulkano/src/sync/event.rs +++ b/vulkano/src/sync/event.rs @@ -11,12 +11,12 @@ use std::mem; use std::ptr; use std::sync::Arc; -use device::Device; -use device::DeviceOwned; use OomError; use Success; use VulkanObject; use check_errors; +use device::Device; +use device::DeviceOwned; use vk; /// Used to block the GPU execution until an event on the CPU occurs. @@ -42,22 +42,24 @@ impl Event { static mut INFOS: vk::EventCreateInfo = vk::EventCreateInfo { sType: vk::STRUCTURE_TYPE_EVENT_CREATE_INFO, pNext: 0 as *const _, //ptr::null(), - flags: 0, // reserved + flags: 0, // reserved }; let mut output = mem::uninitialized(); let vk = device.pointers(); - try!(check_errors(vk.CreateEvent(device.internal_object(), &INFOS, - ptr::null(), &mut output))); + check_errors(vk.CreateEvent(device.internal_object(), + &INFOS, + ptr::null(), + &mut output))?; output }; Ok(Event { - device: device, - event: event, - }) + device: device, + event: event, + }) } - + /// Builds a new event. /// /// # Panic @@ -74,12 +76,12 @@ impl Event { pub fn signaled(&self) -> Result { unsafe { let vk = self.device.pointers(); - let result = try!(check_errors(vk.GetEventStatus(self.device.internal_object(), - self.event))); + let result = check_errors(vk.GetEventStatus(self.device.internal_object(), + self.event))?; match result { Success::EventSet => Ok(true), Success::EventReset => Ok(false), - _ => unreachable!() + _ => unreachable!(), } } } @@ -89,7 +91,7 @@ impl Event { pub fn set_raw(&mut self) -> Result<(), OomError> { unsafe { let vk = self.device.pointers(); - try!(check_errors(vk.SetEvent(self.device.internal_object(), self.event))); + check_errors(vk.SetEvent(self.device.internal_object(), self.event))?; Ok(()) } } @@ -112,7 +114,7 @@ impl Event { pub fn reset_raw(&mut self) -> Result<(), OomError> { unsafe { let vk = self.device.pointers(); - try!(check_errors(vk.ResetEvent(self.device.internal_object(), self.event))); + check_errors(vk.ResetEvent(self.device.internal_object(), self.event))?; Ok(()) } } diff --git a/vulkano/src/sync/fence.rs b/vulkano/src/sync/fence.rs index fdb0c12c..69ad0dbd 100644 --- a/vulkano/src/sync/fence.rs +++ b/vulkano/src/sync/fence.rs @@ -7,6 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use smallvec::SmallVec; use std::error; use std::fmt; use std::mem; @@ -15,16 +16,15 @@ use std::sync::Arc; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; use std::time::Duration; -use smallvec::SmallVec; -use device::Device; -use device::DeviceOwned; use Error; use OomError; use SafeDeref; use Success; use VulkanObject; use check_errors; +use device::Device; +use device::DeviceOwned; use vk; /// A fence is used to know when a command buffer submission has finished its execution. @@ -33,7 +33,9 @@ use vk; /// the same ressource simultaneously (except for concurrent reads). Therefore in order to know /// when the CPU can access a ressource again, a fence has to be used. #[derive(Debug)] -pub struct Fence> where D: SafeDeref { +pub struct Fence> + where D: SafeDeref +{ fence: vk::Fence, device: D, @@ -44,7 +46,9 @@ pub struct Fence> where D: SafeDeref { signaled: AtomicBool, } -impl Fence where D: SafeDeref { +impl Fence + where D: SafeDeref +{ /// Builds a new fence. #[inline] pub fn new(device: D) -> Result, OomError> { @@ -62,39 +66,47 @@ impl Fence where D: SafeDeref { let infos = vk::FenceCreateInfo { sType: vk::STRUCTURE_TYPE_FENCE_CREATE_INFO, pNext: ptr::null(), - flags: if signaled { vk::FENCE_CREATE_SIGNALED_BIT } else { 0 }, + flags: if signaled { + vk::FENCE_CREATE_SIGNALED_BIT + } else { + 0 + }, }; let vk = device.pointers(); let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateFence(device.internal_object(), &infos, - ptr::null(), &mut output))); + check_errors(vk.CreateFence(device.internal_object(), + &infos, + ptr::null(), + &mut output))?; output }; Ok(Fence { - fence: fence, - device: device, - signaled: AtomicBool::new(signaled), - }) + fence: fence, + device: device, + signaled: AtomicBool::new(signaled), + }) } /// Returns true if the fence is signaled. #[inline] pub fn ready(&self) -> Result { unsafe { - if self.signaled.load(Ordering::Relaxed) { return Ok(true); } + if self.signaled.load(Ordering::Relaxed) { + return Ok(true); + } let vk = self.device.pointers(); - let result = try!(check_errors(vk.GetFenceStatus(self.device.internal_object(), - self.fence))); + let result = check_errors(vk.GetFenceStatus(self.device.internal_object(), + self.fence))?; match result { Success::Success => { self.signaled.store(true, Ordering::Relaxed); Ok(true) }, Success::NotReady => Ok(false), - _ => unreachable!() + _ => unreachable!(), } } } @@ -106,18 +118,25 @@ impl Fence where D: SafeDeref { /// If you pass a duration of 0, then the function will return without blocking. pub fn wait(&self, timeout: Option) -> Result<(), FenceWaitError> { unsafe { - if self.signaled.load(Ordering::Relaxed) { return Ok(()); } + if self.signaled.load(Ordering::Relaxed) { + return Ok(()); + } let timeout_ns = if let Some(timeout) = timeout { - timeout.as_secs().saturating_mul(1_000_000_000) - .saturating_add(timeout.subsec_nanos() as u64) + timeout + .as_secs() + .saturating_mul(1_000_000_000) + .saturating_add(timeout.subsec_nanos() as u64) } else { u64::max_value() }; let vk = self.device.pointers(); - let r = try!(check_errors(vk.WaitForFences(self.device.internal_object(), 1, - &self.fence, vk::TRUE, timeout_ns))); + let r = check_errors(vk.WaitForFences(self.device.internal_object(), + 1, + &self.fence, + vk::TRUE, + timeout_ns))?; match r { Success::Success => { @@ -127,7 +146,7 @@ impl Fence where D: SafeDeref { Success::Timeout => { Err(FenceWaitError::Timeout) }, - _ => unreachable!() + _ => unreachable!(), } } } @@ -138,28 +157,34 @@ impl Fence where D: SafeDeref { /// /// Panics if not all fences belong to the same device. pub fn multi_wait<'a, I>(iter: I, timeout: Option) -> Result<(), FenceWaitError> - where I: IntoIterator>, D: 'a + where I: IntoIterator>, + D: 'a { let mut device: Option<&Device> = None; - let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter().filter_map(|fence| { - match &mut device { - dev @ &mut None => *dev = Some(&*fence.device), - &mut Some(ref dev) if &**dev as *const Device == &*fence.device as *const Device => {}, - _ => panic!("Tried to wait for multiple fences that didn't belong to the \ - same device"), - }; + let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter() + .filter_map(|fence| { + match &mut device { + dev @ &mut None => *dev = Some(&*fence.device), + &mut Some(ref dev) + if &**dev as *const Device == &*fence.device as *const Device => {}, + _ => panic!("Tried to wait for multiple fences that didn't belong to the \ + same device"), + }; - if fence.signaled.load(Ordering::Relaxed) { - None - } else { - Some(fence.fence) - } - }).collect(); + if fence.signaled.load(Ordering::Relaxed) { + None + } else { + Some(fence.fence) + } + }) + .collect(); let timeout_ns = if let Some(timeout) = timeout { - timeout.as_secs().saturating_mul(1_000_000_000) - .saturating_add(timeout.subsec_nanos() as u64) + timeout + .as_secs() + .saturating_mul(1_000_000_000) + .saturating_add(timeout.subsec_nanos() as u64) } else { u64::max_value() }; @@ -167,8 +192,11 @@ impl Fence where D: SafeDeref { let r = if let Some(device) = device { unsafe { let vk = device.pointers(); - try!(check_errors(vk.WaitForFences(device.internal_object(), fences.len() as u32, - fences.as_ptr(), vk::TRUE, timeout_ns))) + check_errors(vk.WaitForFences(device.internal_object(), + fences.len() as u32, + fences.as_ptr(), + vk::TRUE, + timeout_ns))? } } else { return Ok(()); @@ -177,7 +205,7 @@ impl Fence where D: SafeDeref { match r { Success::Success => Ok(()), Success::Timeout => Err(FenceWaitError::Timeout), - _ => unreachable!() + _ => unreachable!(), } } @@ -200,25 +228,32 @@ impl Fence where D: SafeDeref { /// - Panics if not all fences belong to the same device. /// pub fn multi_reset<'a, I>(iter: I) - where I: IntoIterator>, D: 'a + where I: IntoIterator>, + D: 'a { let mut device: Option<&Device> = None; - let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter().map(|fence| { - match &mut device { - dev @ &mut None => *dev = Some(&*fence.device), - &mut Some(ref dev) if &**dev as *const Device == &*fence.device as *const Device => {}, - _ => panic!("Tried to reset multiple fences that didn't belong to the same device"), - }; + let fences: SmallVec<[vk::Fence; 8]> = iter.into_iter() + .map(|fence| { + match &mut device { + dev @ &mut None => *dev = Some(&*fence.device), + &mut Some(ref dev) + if &**dev as *const Device == &*fence.device as *const Device => {}, + _ => panic!("Tried to reset multiple fences that didn't belong to the same \ + device"), + }; - fence.signaled.store(false, Ordering::Relaxed); - fence.fence - }).collect(); + fence.signaled.store(false, Ordering::Relaxed); + fence.fence + }) + .collect(); if let Some(device) = device { unsafe { let vk = device.pointers(); - vk.ResetFences(device.internal_object(), fences.len() as u32, fences.as_ptr()); + vk.ResetFences(device.internal_object(), + fences.len() as u32, + fences.as_ptr()); } } } @@ -231,7 +266,9 @@ unsafe impl DeviceOwned for Fence { } } -unsafe impl VulkanObject for Fence where D: SafeDeref { +unsafe impl VulkanObject for Fence + where D: SafeDeref +{ type Object = vk::Fence; #[inline] @@ -240,7 +277,9 @@ unsafe impl VulkanObject for Fence where D: SafeDeref { } } -impl Drop for Fence where D: SafeDeref { +impl Drop for Fence + where D: SafeDeref +{ #[inline] fn drop(&mut self) { unsafe { @@ -277,7 +316,7 @@ impl error::Error for FenceWaitError { fn cause(&self) -> Option<&error::Error> { match *self { FenceWaitError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } @@ -296,7 +335,7 @@ impl From for FenceWaitError { Error::OutOfHostMemory => FenceWaitError::OomError(From::from(err)), Error::OutOfDeviceMemory => FenceWaitError::OomError(From::from(err)), Error::DeviceLost => FenceWaitError::DeviceLostError, - _ => panic!("Unexpected error value: {}", err as i32) + _ => panic!("Unexpected error value: {}", err as i32), } } } @@ -348,7 +387,8 @@ mod tests { let fence1 = Fence::signaled(device1.clone()).unwrap(); let fence2 = Fence::signaled(device2.clone()).unwrap(); - let _ = Fence::multi_wait([&fence1, &fence2].iter().cloned(), Some(Duration::new(0, 10))); + let _ = Fence::multi_wait([&fence1, &fence2].iter().cloned(), + Some(Duration::new(0, 10))); } #[test] diff --git a/vulkano/src/sync/future/fence_signal.rs b/vulkano/src/sync/future/fence_signal.rs index d483a45f..6ae6b63f 100644 --- a/vulkano/src/sync/future/fence_signal.rs +++ b/vulkano/src/sync/future/fence_signal.rs @@ -23,8 +23,8 @@ use image::ImageAccess; use image::ImageLayout; use sync::AccessCheckError; use sync::AccessFlagBits; -use sync::FlushError; use sync::Fence; +use sync::FlushError; use sync::GpuFuture; use sync::PipelineStages; @@ -35,7 +35,7 @@ pub fn then_signal_fence(future: F, behavior: FenceSignalFutureBehavior) -> F { let device = future.device().clone(); - assert!(future.queue().is_some()); // TODO: document + assert!(future.queue().is_some()); // TODO: document let fence = Fence::new(device.clone()).unwrap(); FenceSignalFuture { @@ -53,7 +53,7 @@ pub enum FenceSignalFutureBehavior { /// Wait for the fence to be signalled before submitting any further operation. Block { /// How long to block the current thread. - timeout: Option + timeout: Option, }, } @@ -87,8 +87,11 @@ pub enum FenceSignalFutureBehavior { /// // Later you can wait until you reach the point of `fence_signal`: /// fence_signal.wait(None).unwrap(); /// ``` -#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"] -pub struct FenceSignalFuture where F: GpuFuture { +#[must_use = "Dropping this object will immediately block the thread until the GPU has finished \ + processing the submission"] +pub struct FenceSignalFuture + where F: GpuFuture +{ // Current state. See the docs of `FenceSignalFutureState`. state: Mutex>, // The device of the future. @@ -120,7 +123,9 @@ enum FenceSignalFutureState { Poisonned, } -impl FenceSignalFuture where F: GpuFuture { +impl FenceSignalFuture + where F: GpuFuture +{ /// Blocks the current thread until the fence is signaled by the GPU. Performs a flush if /// necessary. /// @@ -137,16 +142,20 @@ impl FenceSignalFuture where F: GpuFuture { match mem::replace(&mut *state, FenceSignalFutureState::Cleaned) { FenceSignalFutureState::Flushed(previous, fence) => { fence.wait(timeout)?; - unsafe { previous.signal_finished(); } + unsafe { + previous.signal_finished(); + } Ok(()) }, FenceSignalFutureState::Cleaned => Ok(()), - _ => unreachable!() + _ => unreachable!(), } } } -impl FenceSignalFuture where F: GpuFuture { +impl FenceSignalFuture + where F: GpuFuture +{ // Implementation of `cleanup_finished`, but takes a `&self` instead of a `&mut self`. // This is an external function so that we can also call it from an `Arc`. #[inline] @@ -161,7 +170,7 @@ impl FenceSignalFuture where F: GpuFuture { }, Err(_) => { prev.cleanup_finished(); - return + return; }, } }, @@ -183,8 +192,7 @@ impl FenceSignalFuture where F: GpuFuture { // Implementation of `flush`. You must lock the state and pass the mutex guard here. fn flush_impl(&self, state: &mut MutexGuard>) - -> Result<(), FlushError> - { + -> Result<(), FlushError> { unsafe { // In this function we temporarily replace the current state with `Poisonned` at the // beginning, and we take care to always put back a value into `state` before @@ -212,8 +220,11 @@ impl FenceSignalFuture where F: GpuFuture { // There are three possible outcomes for the flush operation: success, partial success // in which case `result` will contain `Err(OutcomeErr::Partial)`, or total failure // in which case `result` will contain `Err(OutcomeErr::Full)`. - enum OutcomeErr { Partial(E), Full(E) } - let result = match try!(previous.build_submission()) { + enum OutcomeErr { + Partial(E), + Full(E), + } + let result = match previous.build_submission()? { SubmitAnyBuilder::Empty => { debug_assert!(!partially_flushed); let mut b = SubmitCommandBufferBuilder::new(); @@ -235,14 +246,18 @@ impl FenceSignalFuture where F: GpuFuture { // assertion. assert!(!cb_builder.has_fence()); cb_builder.set_fence_signal(&fence); - cb_builder.submit(&queue).map_err(|err| OutcomeErr::Full(err.into())) + cb_builder + .submit(&queue) + .map_err(|err| OutcomeErr::Full(err.into())) }, SubmitAnyBuilder::BindSparse(mut sparse) => { debug_assert!(!partially_flushed); // Same remark as `CommandBuffer`. assert!(!sparse.has_fence()); sparse.set_fence_signal(&fence); - sparse.submit(&queue).map_err(|err| OutcomeErr::Full(err.into())) + sparse + .submit(&queue) + .map_err(|err| OutcomeErr::Full(err.into())) }, SubmitAnyBuilder::QueuePresent(present) => { let intermediary_result = if partially_flushed { @@ -258,7 +273,7 @@ impl FenceSignalFuture where F: GpuFuture { }, Err(err) => { Err(OutcomeErr::Full(err.into())) - } + }, } }, }; @@ -295,7 +310,9 @@ impl FenceSignalFutureState { } } -unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { +unsafe impl GpuFuture for FenceSignalFuture + where F: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { self.cleanup_finished_impl() @@ -304,19 +321,20 @@ unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { #[inline] unsafe fn build_submission(&self) -> Result { let mut state = self.state.lock().unwrap(); - try!(self.flush_impl(&mut state)); + self.flush_impl(&mut state)?; match *state { FenceSignalFutureState::Flushed(_, ref fence) => { match self.behavior { FenceSignalFutureBehavior::Block { timeout } => { - try!(fence.wait(timeout)); + fence.wait(timeout)?; }, FenceSignalFutureBehavior::Continue => (), } }, - FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (), - FenceSignalFutureState::Pending(_, _) => unreachable!(), + FenceSignalFutureState::Cleaned | + FenceSignalFutureState::Poisonned => (), + FenceSignalFutureState::Pending(_, _) => unreachable!(), FenceSignalFutureState::PartiallyFlushed(_, _) => unreachable!(), } @@ -336,7 +354,8 @@ unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { FenceSignalFutureState::Flushed(ref prev, _) => { prev.signal_finished(); }, - FenceSignalFutureState::Cleaned | FenceSignalFutureState::Poisonned => (), + FenceSignalFutureState::Cleaned | + FenceSignalFutureState::Poisonned => (), _ => unreachable!(), } } @@ -369,8 +388,9 @@ unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { let state = self.state.lock().unwrap(); if let Some(previous) = state.get_prev() { previous.check_buffer_access(buffer, exclusive, queue) @@ -380,7 +400,8 @@ unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) -> Result, AccessCheckError> { let state = self.state.lock().unwrap(); if let Some(previous) = state.get_prev() { @@ -391,14 +412,18 @@ unsafe impl GpuFuture for FenceSignalFuture where F: GpuFuture { } } -unsafe impl DeviceOwned for FenceSignalFuture where F: GpuFuture { +unsafe impl DeviceOwned for FenceSignalFuture + where F: GpuFuture +{ #[inline] fn device(&self) -> &Arc { &self.device } } -impl Drop for FenceSignalFuture where F: GpuFuture { +impl Drop for FenceSignalFuture + where F: GpuFuture +{ fn drop(&mut self) { let mut state = self.state.lock().unwrap(); @@ -410,7 +435,9 @@ impl Drop for FenceSignalFuture where F: GpuFuture { // This is a normal situation. Submitting worked. // TODO: handle errors? fence.wait(None).unwrap(); - unsafe { previous.signal_finished(); } + unsafe { + previous.signal_finished(); + } }, FenceSignalFutureState::Cleaned => { // Also a normal situation. The user called `cleanup_finished()` before dropping. @@ -420,14 +447,16 @@ impl Drop for FenceSignalFuture where F: GpuFuture { }, FenceSignalFutureState::Pending(_, _) | FenceSignalFutureState::PartiallyFlushed(_, _) => { - // Flushing produced an error. There's nothing more we can do except drop the + // Flushing produced an error. There's nothing more we can do except drop the // previous future and let it block the current queue. }, } } } -unsafe impl GpuFuture for Arc> where F: GpuFuture { +unsafe impl GpuFuture for Arc> + where F: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { self.cleanup_finished_impl() @@ -461,16 +490,16 @@ unsafe impl GpuFuture for Arc> where F: GpuFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { (**self).check_buffer_access(buffer, exclusive, queue) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { (**self).check_image_access(image, layout, exclusive, queue) } } diff --git a/vulkano/src/sync/future/join.rs b/vulkano/src/sync/future/join.rs index 8ab1daa3..3c19d800 100644 --- a/vulkano/src/sync/future/join.rs +++ b/vulkano/src/sync/future/join.rs @@ -28,9 +28,11 @@ use VulkanObject; // TODO: handle errors #[inline] pub fn join(first: F, second: S) -> JoinFuture - where F: GpuFuture, S: GpuFuture + where F: GpuFuture, + S: GpuFuture { - assert_eq!(first.device().internal_object(), second.device().internal_object()); + assert_eq!(first.device().internal_object(), + second.device().internal_object()); if !first.queue_change_allowed() && !second.queue_change_allowed() { assert!(first.queue().unwrap().is_same(&second.queue().unwrap())); @@ -49,16 +51,23 @@ pub struct JoinFuture { second: B, } -unsafe impl DeviceOwned for JoinFuture where A: DeviceOwned, B: DeviceOwned { +unsafe impl DeviceOwned for JoinFuture + where A: DeviceOwned, + B: DeviceOwned +{ #[inline] fn device(&self) -> &Arc { let device = self.first.device(); - debug_assert_eq!(self.second.device().internal_object(), device.internal_object()); + debug_assert_eq!(self.second.device().internal_object(), + device.internal_object()); device } } -unsafe impl GpuFuture for JoinFuture where A: GpuFuture, B: GpuFuture { +unsafe impl GpuFuture for JoinFuture + where A: GpuFuture, + B: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { self.first.cleanup_finished(); @@ -69,8 +78,8 @@ unsafe impl GpuFuture for JoinFuture where A: GpuFuture, B: GpuFutur fn flush(&self) -> Result<(), FlushError> { // Since each future remembers whether it has been flushed, there's no safety issue here // if we call this function multiple times. - try!(self.first.flush()); - try!(self.second.flush()); + self.first.flush()?; + self.second.flush()?; Ok(()) } @@ -78,79 +87,79 @@ unsafe impl GpuFuture for JoinFuture where A: GpuFuture, B: GpuFutur unsafe fn build_submission(&self) -> Result { // TODO: review this function - let first = try!(self.first.build_submission()); - let second = try!(self.second.build_submission()); + let first = self.first.build_submission()?; + let second = self.second.build_submission()?; Ok(match (first, second) { - (SubmitAnyBuilder::Empty, b) => b, - (a, SubmitAnyBuilder::Empty) => a, - (SubmitAnyBuilder::SemaphoresWait(mut a), SubmitAnyBuilder::SemaphoresWait(b)) => { - a.merge(b); - SubmitAnyBuilder::SemaphoresWait(a) - }, - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::CommandBuffer(b)) => { - try!(b.submit(&self.second.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(a) - }, - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - try!(a.submit(&self.first.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(b) - }, - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::QueuePresent(b)) => { - try!(b.submit(&self.second.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(a) - }, - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - try!(a.submit(&self.first.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(b) - }, - (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::BindSparse(b)) => { - try!(b.submit(&self.second.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(a) - }, - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::SemaphoresWait(b)) => { - try!(a.submit(&self.first.queue().clone().unwrap())); - SubmitAnyBuilder::SemaphoresWait(b) - }, - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::CommandBuffer(b)) => { - // TODO: we may want to add debug asserts here - let new = a.merge(b); - SubmitAnyBuilder::CommandBuffer(new) - }, - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::QueuePresent(b)) => { - try!(a.submit(&self.first.queue().clone().unwrap())); - try!(b.submit(&self.second.queue().clone().unwrap())); - SubmitAnyBuilder::Empty - }, - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::QueuePresent(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::CommandBuffer(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::QueuePresent(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::BindSparse(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::CommandBuffer(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::BindSparse(b)) => { - unimplemented!() - }, - (SubmitAnyBuilder::BindSparse(mut a), SubmitAnyBuilder::BindSparse(b)) => { - match a.merge(b) { - Ok(()) => SubmitAnyBuilder::BindSparse(a), - Err(_) => { - // TODO: this happens if both bind sparse have been given a fence already - // annoying, but not impossible, to handle - unimplemented!() - } - } - }, - }) + (SubmitAnyBuilder::Empty, b) => b, + (a, SubmitAnyBuilder::Empty) => a, + (SubmitAnyBuilder::SemaphoresWait(mut a), SubmitAnyBuilder::SemaphoresWait(b)) => { + a.merge(b); + SubmitAnyBuilder::SemaphoresWait(a) + }, + (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::CommandBuffer(b)) => { + b.submit(&self.second.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(a) + }, + (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::SemaphoresWait(b)) => { + a.submit(&self.first.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(b) + }, + (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::QueuePresent(b)) => { + b.submit(&self.second.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(a) + }, + (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::SemaphoresWait(b)) => { + a.submit(&self.first.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(b) + }, + (SubmitAnyBuilder::SemaphoresWait(a), SubmitAnyBuilder::BindSparse(b)) => { + b.submit(&self.second.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(a) + }, + (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::SemaphoresWait(b)) => { + a.submit(&self.first.queue().clone().unwrap())?; + SubmitAnyBuilder::SemaphoresWait(b) + }, + (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::CommandBuffer(b)) => { + // TODO: we may want to add debug asserts here + let new = a.merge(b); + SubmitAnyBuilder::CommandBuffer(new) + }, + (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::QueuePresent(b)) => { + a.submit(&self.first.queue().clone().unwrap())?; + b.submit(&self.second.queue().clone().unwrap())?; + SubmitAnyBuilder::Empty + }, + (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::QueuePresent(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::CommandBuffer(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::QueuePresent(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::QueuePresent(a), SubmitAnyBuilder::BindSparse(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::BindSparse(a), SubmitAnyBuilder::CommandBuffer(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::CommandBuffer(a), SubmitAnyBuilder::BindSparse(b)) => { + unimplemented!() + }, + (SubmitAnyBuilder::BindSparse(mut a), SubmitAnyBuilder::BindSparse(b)) => { + match a.merge(b) { + Ok(()) => SubmitAnyBuilder::BindSparse(a), + Err(_) => { + // TODO: this happens if both bind sparse have been given a fence already + // annoying, but not impossible, to handle + unimplemented!() + }, + } + }, + }) } #[inline] @@ -183,21 +192,24 @@ unsafe impl GpuFuture for JoinFuture where A: GpuFuture, B: GpuFutur } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { let first = self.first.check_buffer_access(buffer, exclusive, queue); let second = self.second.check_buffer_access(buffer, exclusive, queue); - debug_assert!(!exclusive || !(first.is_ok() && second.is_ok()), "Two futures gave \ - exclusive access to the \ - same resource"); + debug_assert!(!exclusive || !(first.is_ok() && second.is_ok()), + "Two futures gave exclusive access to the same resource"); match (first, second) { (v, Err(AccessCheckError::Unknown)) => v, (Err(AccessCheckError::Unknown), v) => v, - (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => Err(AccessCheckError::Denied(e1)), // TODO: which one? - (Ok(_), Err(AccessCheckError::Denied(_))) | (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!("Contradictory information between two futures"), + (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => + Err(AccessCheckError::Denied(e1)), // TODO: which one? + (Ok(_), Err(AccessCheckError::Denied(_))) | + (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!("Contradictory information \ + between two futures"), (Ok(None), Ok(None)) => Ok(None), - (Ok(Some(a)), Ok(None)) | (Ok(None), Ok(Some(a))) => Ok(Some(a)), + (Ok(Some(a)), Ok(None)) | + (Ok(None), Ok(Some(a))) => Ok(Some(a)), (Ok(Some((a1, a2))), Ok(Some((b1, b2)))) => { Ok(Some((a1 | b1, a2 | b2))) }, @@ -205,21 +217,26 @@ unsafe impl GpuFuture for JoinFuture where A: GpuFuture, B: GpuFutur } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - let first = self.first.check_image_access(image, layout, exclusive, queue); - let second = self.second.check_image_access(image, layout, exclusive, queue); - debug_assert!(!exclusive || !(first.is_ok() && second.is_ok()), "Two futures gave \ - exclusive access to the \ - same resource"); + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { + let first = self.first + .check_image_access(image, layout, exclusive, queue); + let second = self.second + .check_image_access(image, layout, exclusive, queue); + debug_assert!(!exclusive || !(first.is_ok() && second.is_ok()), + "Two futures gave exclusive access to the same resource"); match (first, second) { (v, Err(AccessCheckError::Unknown)) => v, (Err(AccessCheckError::Unknown), v) => v, - (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => Err(AccessCheckError::Denied(e1)), // TODO: which one? - (Ok(_), Err(AccessCheckError::Denied(_))) | (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!("Contradictory information between two futures"), + (Err(AccessCheckError::Denied(e1)), Err(AccessCheckError::Denied(e2))) => + Err(AccessCheckError::Denied(e1)), // TODO: which one? + (Ok(_), Err(AccessCheckError::Denied(_))) | + (Err(AccessCheckError::Denied(_)), Ok(_)) => panic!("Contradictory information \ + between two futures"), (Ok(None), Ok(None)) => Ok(None), - (Ok(Some(a)), Ok(None)) | (Ok(None), Ok(Some(a))) => Ok(Some(a)), + (Ok(Some(a)), Ok(None)) | + (Ok(None), Ok(Some(a))) => Ok(Some(a)), (Ok(Some((a1, a2))), Ok(Some((b1, b2)))) => { Ok(Some((a1 | b1, a2 | b2))) }, diff --git a/vulkano/src/sync/future/mod.rs b/vulkano/src/sync/future/mod.rs index 9adfa45e..52ed70aa 100644 --- a/vulkano/src/sync/future/mod.rs +++ b/vulkano/src/sync/future/mod.rs @@ -11,29 +11,29 @@ use std::error; use std::fmt; use std::sync::Arc; +use OomError; use buffer::BufferAccess; use command_buffer::CommandBuffer; use command_buffer::CommandBufferExecError; use command_buffer::CommandBufferExecFuture; use command_buffer::submit::SubmitAnyBuilder; use command_buffer::submit::SubmitBindSparseError; -use command_buffer::submit::SubmitPresentError; use command_buffer::submit::SubmitCommandBufferError; +use command_buffer::submit::SubmitPresentError; use device::DeviceOwned; use device::Queue; use image::ImageAccess; use image::ImageLayout; use swapchain; -use swapchain::Swapchain; use swapchain::PresentFuture; +use swapchain::Swapchain; use sync::AccessFlagBits; use sync::FenceWaitError; use sync::PipelineStages; -use OomError; -pub use self::now::{now, NowFuture}; pub use self::fence_signal::{FenceSignalFuture, FenceSignalFutureBehavior}; pub use self::join::JoinFuture; +pub use self::now::{NowFuture, now}; pub use self::semaphore_signal::SemaphoreSignalFuture; mod now; @@ -50,7 +50,7 @@ pub unsafe trait GpuFuture: DeviceOwned { /// resources used by these submissions. /// /// It is highly recommended to call `cleanup_finished` from time to time. Doing so will - /// prevent memory usage from increasing over time, and will also destroy the locks on + /// prevent memory usage from increasing over time, and will also destroy the locks on /// resources used by the GPU. fn cleanup_finished(&mut self); @@ -60,7 +60,7 @@ pub unsafe trait GpuFuture: DeviceOwned { /// /// It is the responsibility of the caller to ensure that the submission is going to be /// submitted only once. However keep in mind that this function can perfectly be called - /// multiple times (as long as the returned object is only submitted once). + /// multiple times (as long as the returned object is only submitted once). /// Also note that calling `flush()` on the future may change the value returned by /// `build_submission()`. /// @@ -129,12 +129,14 @@ pub unsafe trait GpuFuture: DeviceOwned { /// > **Note**: Keep in mind that changing the layout of an image also requires exclusive /// > access. fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, - queue: &Queue) -> Result, AccessCheckError>; + queue: &Queue) + -> Result, AccessCheckError>; /// Joins this future with another one, representing the moment when both events have happened. // TODO: handle errors fn join(self, other: F) -> JoinFuture - where Self: Sized, F: GpuFuture + where Self: Sized, + F: GpuFuture { join::join(self, other) } @@ -146,7 +148,8 @@ pub unsafe trait GpuFuture: DeviceOwned { #[inline] fn then_execute(self, queue: Arc, command_buffer: Cb) -> Result, CommandBufferExecError> - where Self: Sized, Cb: CommandBuffer + 'static + where Self: Sized, + Cb: CommandBuffer + 'static { command_buffer.execute_after(self, queue) } @@ -156,9 +159,11 @@ pub unsafe trait GpuFuture: DeviceOwned { /// > **Note**: This is just a shortcut function. The actual implementation is in the /// > `CommandBuffer` trait. #[inline] - fn then_execute_same_queue(self, command_buffer: Cb) - -> Result, CommandBufferExecError> - where Self: Sized, Cb: CommandBuffer + 'static + fn then_execute_same_queue( + self, command_buffer: Cb) + -> Result, CommandBufferExecError> + where Self: Sized, + Cb: CommandBuffer + 'static { let queue = self.queue().unwrap().clone(); command_buffer.execute_after(self, queue) @@ -169,7 +174,9 @@ pub unsafe trait GpuFuture: DeviceOwned { /// Call this function when you want to execute some operations on a queue and want to see the /// result on another queue. #[inline] - fn then_signal_semaphore(self) -> SemaphoreSignalFuture where Self: Sized { + fn then_signal_semaphore(self) -> SemaphoreSignalFuture + where Self: Sized + { semaphore_signal::then_signal_semaphore(self) } @@ -200,7 +207,9 @@ pub unsafe trait GpuFuture: DeviceOwned { /// > **Note**: More often than not you want to immediately flush the future after calling this /// > function. If so, consider using `then_signal_fence_and_flush`. #[inline] - fn then_signal_fence(self) -> FenceSignalFuture where Self: Sized { + fn then_signal_fence(self) -> FenceSignalFuture + where Self: Sized + { fence_signal::then_signal_fence(self, FenceSignalFutureBehavior::Continue) } @@ -224,14 +233,17 @@ pub unsafe trait GpuFuture: DeviceOwned { /// > **Note**: This is just a shortcut for the `Swapchain::present()` function. #[inline] fn then_swapchain_present(self, queue: Arc, swapchain: Arc, - image_index: usize) -> PresentFuture + image_index: usize) + -> PresentFuture where Self: Sized { swapchain::present(swapchain, self, queue, image_index) } } -unsafe impl GpuFuture for Box where F: GpuFuture { +unsafe impl GpuFuture for Box + where F: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { (**self).cleanup_finished() @@ -263,16 +275,16 @@ unsafe impl GpuFuture for Box where F: GpuFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { (**self).check_buffer_access(buffer, exclusive, queue) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { (**self).check_image_access(image, layout, exclusive, queue) } } @@ -316,7 +328,7 @@ impl error::Error for AccessError { "the resource is already in use, and there is no tracking of concurrent usages" }, AccessError::UnexpectedImageLayout { .. } => { - unimplemented!() // TODO: find a description + unimplemented!() // TODO: find a description }, AccessError::ImageNotInitialized { .. } => { "trying to use an image without transitionning it from the undefined or \ @@ -409,7 +421,8 @@ impl error::Error for FlushError { FlushError::DeviceLost => "the connection to the device has been lost", FlushError::SurfaceLost => "the surface of this swapchain is no longer valid", FlushError::OutOfDate => "the swapchain needs to be recreated", - FlushError::Timeout => "the flush operation needed to block, but the timeout has elapsed", + FlushError::Timeout => "the flush operation needed to block, but the timeout has \ + elapsed", } } @@ -418,7 +431,7 @@ impl error::Error for FlushError { match *self { FlushError::AccessError(ref err) => Some(err), FlushError::OomError(ref err) => Some(err), - _ => None + _ => None, } } } diff --git a/vulkano/src/sync/future/now.rs b/vulkano/src/sync/future/now.rs index 4931b3a7..836ebcbd 100644 --- a/vulkano/src/sync/future/now.rs +++ b/vulkano/src/sync/future/now.rs @@ -25,9 +25,7 @@ use sync::PipelineStages; /// Builds a future that represents "now". #[inline] pub fn now(device: Arc) -> NowFuture { - NowFuture { - device: device, - } + NowFuture { device: device } } /// A dummy future that represents "now". @@ -65,16 +63,16 @@ unsafe impl GpuFuture for NowFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { Err(AccessCheckError::Unknown) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { Err(AccessCheckError::Unknown) } } diff --git a/vulkano/src/sync/future/semaphore_signal.rs b/vulkano/src/sync/future/semaphore_signal.rs index d555e23b..66f82146 100644 --- a/vulkano/src/sync/future/semaphore_signal.rs +++ b/vulkano/src/sync/future/semaphore_signal.rs @@ -30,10 +30,12 @@ use sync::Semaphore; /// Builds a new semaphore signal future. #[inline] -pub fn then_signal_semaphore(future: F) -> SemaphoreSignalFuture where F: GpuFuture { +pub fn then_signal_semaphore(future: F) -> SemaphoreSignalFuture + where F: GpuFuture +{ let device = future.device().clone(); - assert!(future.queue().is_some()); // TODO: document + assert!(future.queue().is_some()); // TODO: document SemaphoreSignalFuture { previous: future, @@ -44,8 +46,11 @@ pub fn then_signal_semaphore(future: F) -> SemaphoreSignalFuture where F: } /// Represents a semaphore being signaled after a previous event. -#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"] -pub struct SemaphoreSignalFuture where F: GpuFuture { +#[must_use = "Dropping this object will immediately block the thread until the GPU has finished \ + processing the submission"] +pub struct SemaphoreSignalFuture + where F: GpuFuture +{ previous: F, semaphore: Semaphore, // True if the signaling command has already been submitted. @@ -55,7 +60,9 @@ pub struct SemaphoreSignalFuture where F: GpuFuture { finished: AtomicBool, } -unsafe impl GpuFuture for SemaphoreSignalFuture where F: GpuFuture { +unsafe impl GpuFuture for SemaphoreSignalFuture + where F: GpuFuture +{ #[inline] fn cleanup_finished(&mut self) { self.previous.cleanup_finished(); @@ -64,7 +71,7 @@ unsafe impl GpuFuture for SemaphoreSignalFuture where F: GpuFuture { #[inline] unsafe fn build_submission(&self) -> Result { // Flushing the signaling part, since it must always be submitted before the waiting part. - try!(self.flush()); + self.flush()?; let mut sem = SubmitSemaphoresWaitBuilder::new(); sem.add_wait_semaphore(&self.semaphore); @@ -81,33 +88,33 @@ unsafe impl GpuFuture for SemaphoreSignalFuture where F: GpuFuture { let queue = self.previous.queue().unwrap().clone(); - match try!(self.previous.build_submission()) { + match self.previous.build_submission()? { SubmitAnyBuilder::Empty => { let mut builder = SubmitCommandBufferBuilder::new(); builder.add_signal_semaphore(&self.semaphore); - try!(builder.submit(&queue)); + builder.submit(&queue)?; }, SubmitAnyBuilder::SemaphoresWait(sem) => { let mut builder: SubmitCommandBufferBuilder = sem.into(); builder.add_signal_semaphore(&self.semaphore); - try!(builder.submit(&queue)); + builder.submit(&queue)?; }, SubmitAnyBuilder::CommandBuffer(mut builder) => { debug_assert_eq!(builder.num_signal_semaphores(), 0); builder.add_signal_semaphore(&self.semaphore); - try!(builder.submit(&queue)); + builder.submit(&queue)?; }, SubmitAnyBuilder::BindSparse(_) => { - unimplemented!() // TODO: how to do that? + unimplemented!() // TODO: how to do that? /*debug_assert_eq!(builder.num_signal_semaphores(), 0); builder.add_signal_semaphore(&self.semaphore); try!(builder.submit(&queue));*/ }, SubmitAnyBuilder::QueuePresent(present) => { - try!(present.submit(&queue)); + present.submit(&queue)?; let mut builder = SubmitCommandBufferBuilder::new(); builder.add_signal_semaphore(&self.semaphore); - try!(builder.submit(&queue)); // FIXME: problematic because if we return an error and flush() is called again, then we'll submit the present twice + builder.submit(&queue)?; // FIXME: problematic because if we return an error and flush() is called again, then we'll submit the present twice }, }; @@ -135,28 +142,36 @@ unsafe impl GpuFuture for SemaphoreSignalFuture where F: GpuFuture { } #[inline] - fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - self.previous.check_buffer_access(buffer, exclusive, queue).map(|_| None) + fn check_buffer_access( + &self, buffer: &BufferAccess, exclusive: bool, queue: &Queue) + -> Result, AccessCheckError> { + self.previous + .check_buffer_access(buffer, exclusive, queue) + .map(|_| None) } #[inline] - fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue) - -> Result, AccessCheckError> - { - self.previous.check_image_access(image, layout, exclusive, queue).map(|_| None) + fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, + queue: &Queue) + -> Result, AccessCheckError> { + self.previous + .check_image_access(image, layout, exclusive, queue) + .map(|_| None) } } -unsafe impl DeviceOwned for SemaphoreSignalFuture where F: GpuFuture { +unsafe impl DeviceOwned for SemaphoreSignalFuture + where F: GpuFuture +{ #[inline] fn device(&self) -> &Arc { self.semaphore.device() } } -impl Drop for SemaphoreSignalFuture where F: GpuFuture { +impl Drop for SemaphoreSignalFuture + where F: GpuFuture +{ fn drop(&mut self) { unsafe { if !*self.finished.get_mut() { diff --git a/vulkano/src/sync/mod.rs b/vulkano/src/sync/mod.rs index 15f9b4ac..ebd1ed8b 100644 --- a/vulkano/src/sync/mod.rs +++ b/vulkano/src/sync/mod.rs @@ -12,7 +12,7 @@ //! Just like for CPU code, you have to ensure that buffers and images are not accessed mutably by //! multiple GPU queues simultaneously and that they are not accessed mutably by the CPU and by the //! GPU simultaneously. -//! +//! //! This safety is enforced at runtime by vulkano but it is not magic and you will require some //! knowledge if you want to avoid errors. //! @@ -103,21 +103,21 @@ //! TODO: talk about fence + semaphore simultaneously //! TODO: talk about using fences to clean up -use std::sync::Arc; use device::Queue; +use std::sync::Arc; pub use self::event::Event; pub use self::fence::Fence; pub use self::fence::FenceWaitError; -pub use self::future::now; -pub use self::future::NowFuture; -pub use self::future::GpuFuture; -pub use self::future::SemaphoreSignalFuture; -pub use self::future::FenceSignalFuture; -pub use self::future::JoinFuture; -pub use self::future::AccessError; pub use self::future::AccessCheckError; +pub use self::future::AccessError; +pub use self::future::FenceSignalFuture; pub use self::future::FlushError; +pub use self::future::GpuFuture; +pub use self::future::JoinFuture; +pub use self::future::NowFuture; +pub use self::future::SemaphoreSignalFuture; +pub use self::future::now; pub use self::pipeline::AccessFlagBits; pub use self::pipeline::PipelineStages; pub use self::semaphore::Semaphore; @@ -139,7 +139,7 @@ pub enum SharingMode { /// The resource is used is only one queue family. Exclusive(u32), /// The resource is used in multiple queue families. Can be slower than `Exclusive`. - Concurrent(Vec), // TODO: Vec is too expensive here + Concurrent(Vec), // TODO: Vec is too expensive here } impl<'a> From<&'a Arc> for SharingMode { @@ -152,15 +152,15 @@ impl<'a> From<&'a Arc> for SharingMode { impl<'a> From<&'a [&'a Arc]> for SharingMode { #[inline] fn from(queues: &'a [&'a Arc]) -> SharingMode { - SharingMode::Concurrent(queues.iter().map(|queue| { - queue.family().id() - }).collect()) + SharingMode::Concurrent(queues.iter().map(|queue| queue.family().id()).collect()) } } /// Declares in which queue(s) a resource can be used. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum Sharing where I: Iterator { +pub enum Sharing + where I: Iterator +{ /// The resource is used is only one queue family. Exclusive, /// The resource is used in multiple queue families. Can be slower than `Exclusive`. diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index 4fb6f360..ee2355e0 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -196,7 +196,8 @@ impl AccessFlagBits { if (self.uniform_read || self.shader_read || self.shader_write) && !stages.vertex_shader && !stages.tessellation_control_shader && !stages.tessellation_evaluation_shader && !stages.geometry_shader && - !stages.fragment_shader && !stages.compute_shader && !stages.all_graphics + !stages.fragment_shader && + !stages.compute_shader && !stages.all_graphics { return false; } @@ -212,7 +213,8 @@ impl AccessFlagBits { } if (self.depth_stencil_attachment_read || self.depth_stencil_attachment_write) && - !stages.early_fragment_tests && !stages.late_fragment_tests && !stages.all_graphics + !stages.early_fragment_tests && !stages.late_fragment_tests && + !stages.all_graphics { return false; } diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index bc16a8de..bda41b3c 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -11,25 +11,29 @@ use std::mem; use std::ptr; use std::sync::Arc; -use device::Device; -use device::DeviceOwned; use OomError; use SafeDeref; use VulkanObject; use check_errors; +use device::Device; +use device::DeviceOwned; use vk; /// Used to provide synchronization between command buffers during their execution. -/// +/// /// It is similar to a fence, except that it is purely on the GPU side. The CPU can't query a /// semaphore's status or wait for it to be signaled. #[derive(Debug)] -pub struct Semaphore> where D: SafeDeref { +pub struct Semaphore> + where D: SafeDeref +{ semaphore: vk::Semaphore, device: D, } -impl Semaphore where D: SafeDeref { +impl Semaphore + where D: SafeDeref +{ /// Builds a new semaphore. #[inline] pub fn new(device: D) -> Result, OomError> { @@ -37,21 +41,23 @@ impl Semaphore where D: SafeDeref { // since the creation is constant, we use a `static` instead of a struct on the stack static mut INFOS: vk::SemaphoreCreateInfo = vk::SemaphoreCreateInfo { sType: vk::STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - pNext: 0 as *const _, // ptr::null() - flags: 0, // reserved + pNext: 0 as *const _, // ptr::null() + flags: 0, // reserved }; let vk = device.pointers(); let mut output = mem::uninitialized(); - try!(check_errors(vk.CreateSemaphore(device.internal_object(), &INFOS, - ptr::null(), &mut output))); + check_errors(vk.CreateSemaphore(device.internal_object(), + &INFOS, + ptr::null(), + &mut output))?; output }; Ok(Semaphore { - device: device, - semaphore: semaphore, - }) + device: device, + semaphore: semaphore, + }) } } @@ -62,7 +68,9 @@ unsafe impl DeviceOwned for Semaphore { } } -unsafe impl VulkanObject for Semaphore where D: SafeDeref { +unsafe impl VulkanObject for Semaphore + where D: SafeDeref +{ type Object = vk::Semaphore; #[inline] @@ -71,7 +79,9 @@ unsafe impl VulkanObject for Semaphore where D: SafeDeref } } -impl Drop for Semaphore where D: SafeDeref { +impl Drop for Semaphore + where D: SafeDeref +{ #[inline] fn drop(&mut self) { unsafe { diff --git a/vulkano/src/version.rs b/vulkano/src/version.rs index 28409e59..01be60d2 100644 --- a/vulkano/src/version.rs +++ b/vulkano/src/version.rs @@ -46,12 +46,12 @@ impl Ord for Version { fn cmp(&self, other: &Version) -> Ordering { match self.major.cmp(&other.major) { Ordering::Equal => (), - o => return o + o => return o, }; match self.minor.cmp(&other.minor) { Ordering::Equal => (), - o => return o + o => return o, }; self.patch.cmp(&other.patch) @@ -65,7 +65,7 @@ impl Version { Version { major: ((value & 0xffc00000) >> 22) as u16, minor: ((value & 0x003ff000) >> 12) as u16, - patch: (value & 0x00000fff) as u16, + patch: (value & 0x00000fff) as u16, } } @@ -90,28 +90,56 @@ mod tests { #[test] fn into_vk_version() { - let version = Version { major: 1, minor: 0, patch: 0 }; + let version = Version { + major: 1, + minor: 0, + patch: 0, + }; assert_eq!(version.into_vulkan_version(), 0x400000); } #[test] fn greater_major() { - let v1 = Version { major: 1, minor: 0, patch: 0 }; - let v2 = Version { major: 2, minor: 0, patch: 0 }; + let v1 = Version { + major: 1, + minor: 0, + patch: 0, + }; + let v2 = Version { + major: 2, + minor: 0, + patch: 0, + }; assert!(v2 > v1); } #[test] fn greater_minor() { - let v1 = Version { major: 1, minor: 1, patch: 0 }; - let v2 = Version { major: 1, minor: 3, patch: 0 }; + let v1 = Version { + major: 1, + minor: 1, + patch: 0, + }; + let v2 = Version { + major: 1, + minor: 3, + patch: 0, + }; assert!(v2 > v1); } #[test] fn greater_patch() { - let v1 = Version { major: 1, minor: 0, patch: 4 }; - let v2 = Version { major: 1, minor: 0, patch: 5 }; + let v1 = Version { + major: 1, + minor: 0, + patch: 4, + }; + let v2 = Version { + major: 1, + minor: 0, + patch: 5, + }; assert!(v2 > v1); } }