1 // Copyright (c) 2017 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9
10 use std::error;
11 use std::fmt;
12
13 use crate::buffer::BufferAccess;
14 use crate::buffer::TypedBufferAccess;
15 use crate::device::Device;
16 use crate::device::DeviceOwned;
17 use crate::pipeline::input_assembly::Index;
18 use crate::VulkanObject;
19
20 /// Checks whether an index buffer can be bound.
21 ///
22 /// # Panic
23 ///
24 /// - Panics if the buffer was not created with `device`.
25 ///
check_index_buffer<B, I>( device: &Device, buffer: &B, ) -> Result<CheckIndexBuffer, CheckIndexBufferError> where B: ?Sized + BufferAccess + TypedBufferAccess<Content = [I]>, I: Index,26 pub fn check_index_buffer<B, I>(
27 device: &Device,
28 buffer: &B,
29 ) -> Result<CheckIndexBuffer, CheckIndexBufferError>
30 where
31 B: ?Sized + BufferAccess + TypedBufferAccess<Content = [I]>,
32 I: Index,
33 {
34 assert_eq!(
35 buffer.inner().buffer.device().internal_object(),
36 device.internal_object()
37 );
38
39 if !buffer.inner().buffer.usage().index_buffer {
40 return Err(CheckIndexBufferError::BufferMissingUsage);
41 }
42
43 // TODO: The sum of offset and the address of the range of VkDeviceMemory object that is
44 // backing buffer, must be a multiple of the type indicated by indexType
45
46 // TODO: full_draw_index_uint32 feature
47
48 Ok(CheckIndexBuffer {
49 num_indices: buffer.len() as u32,
50 })
51 }
52
53 /// Information returned if `check_index_buffer` succeeds.
54 pub struct CheckIndexBuffer {
55 /// Number of indices in the index buffer.
56 pub num_indices: u32,
57 }
58
59 /// Error that can happen when checking whether binding an index buffer is valid.
60 #[derive(Debug, Copy, Clone)]
61 pub enum CheckIndexBufferError {
62 /// The "index buffer" usage must be enabled on the index buffer.
63 BufferMissingUsage,
64 /// The data or size must be 4-bytes aligned.
65 WrongAlignment,
66 /// The type of the indices is not supported by the device.
67 UnsupportIndexType,
68 }
69
70 impl error::Error for CheckIndexBufferError {}
71
72 impl fmt::Display for CheckIndexBufferError {
73 #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>74 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
75 write!(
76 fmt,
77 "{}",
78 match *self {
79 CheckIndexBufferError::BufferMissingUsage => {
80 "the index buffer usage must be enabled on the index buffer"
81 }
82 CheckIndexBufferError::WrongAlignment => {
83 "the sum of offset and the address of the range of VkDeviceMemory object that is \
84 backing buffer, must be a multiple of the type indicated by indexType"
85 }
86 CheckIndexBufferError::UnsupportIndexType => {
87 "the type of the indices is not supported by the device"
88 }
89 }
90 )
91 }
92 }
93
94 #[cfg(test)]
95 mod tests {
96 use super::*;
97 use crate::buffer::BufferUsage;
98 use crate::buffer::CpuAccessibleBuffer;
99
100 #[test]
num_indices()101 fn num_indices() {
102 let (device, queue) = gfx_dev_and_queue!();
103 let buffer = CpuAccessibleBuffer::from_iter(
104 device.clone(),
105 BufferUsage::index_buffer(),
106 false,
107 0..500u32,
108 )
109 .unwrap();
110
111 match check_index_buffer(&device, &buffer) {
112 Ok(CheckIndexBuffer { num_indices }) => {
113 assert_eq!(num_indices, 500);
114 }
115 _ => panic!(),
116 }
117 }
118
119 #[test]
missing_usage()120 fn missing_usage() {
121 let (device, queue) = gfx_dev_and_queue!();
122 let buffer = CpuAccessibleBuffer::from_iter(
123 device.clone(),
124 BufferUsage::vertex_buffer(),
125 false,
126 0..500u32,
127 )
128 .unwrap();
129
130 match check_index_buffer(&device, &buffer) {
131 Err(CheckIndexBufferError::BufferMissingUsage) => (),
132 _ => panic!(),
133 }
134 }
135
136 #[test]
wrong_device()137 fn wrong_device() {
138 let (dev1, queue) = gfx_dev_and_queue!();
139 let (dev2, _) = gfx_dev_and_queue!();
140
141 let buffer =
142 CpuAccessibleBuffer::from_iter(dev1, BufferUsage::all(), false, 0..500u32).unwrap();
143
144 assert_should_panic!({
145 let _ = check_index_buffer(&dev2, &buffer);
146 });
147 }
148 }
149