1 //! Memory buffers.
2 //!
3 //! # Buffer
4 //!
5 //! Buffers interpret memory slices as linear contiguous data array.
6 //! They can be used as shader resources, vertex buffers, index buffers or for
7 //! specifying the action commands for indirect execution.
8 
9 use crate::{device, format, Backend, IndexType};
10 
11 /// An offset inside a buffer, in bytes.
12 pub type Offset = u64;
13 
14 /// A subrange of the buffer.
15 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
16 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17 pub struct SubRange {
18     /// Offset to the subrange.
19     pub offset: Offset,
20     /// Size of the subrange, or None for the remaining size of the buffer.
21     pub size: Option<Offset>,
22 }
23 
24 impl SubRange {
25     /// Whole buffer subrange.
26     pub const WHOLE: Self = SubRange {
27         offset: 0,
28         size: None,
29     };
30 
31     /// Return the stored size, if present, or computed size based on the limit.
size_to(&self, limit: Offset) -> Offset32     pub fn size_to(&self, limit: Offset) -> Offset {
33         self.size.unwrap_or(limit - self.offset)
34     }
35 }
36 
37 /// Buffer state.
38 pub type State = Access;
39 
40 /// Error creating a buffer.
41 #[derive(Clone, Debug, PartialEq)]
42 pub enum CreationError {
43     /// Out of either host or device memory.
44     OutOfMemory(device::OutOfMemory),
45 
46     /// Requested buffer usage is not supported.
47     ///
48     /// Older GL version don't support constant buffers or multiple usage flags.
49     UnsupportedUsage {
50         /// Unsupported usage passed on buffer creation.
51         usage: Usage,
52     },
53 }
54 
55 impl From<device::OutOfMemory> for CreationError {
from(error: device::OutOfMemory) -> Self56     fn from(error: device::OutOfMemory) -> Self {
57         CreationError::OutOfMemory(error)
58     }
59 }
60 
61 impl std::fmt::Display for CreationError {
fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result62     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63         match self {
64             CreationError::OutOfMemory(err) => write!(fmt, "Failed to create buffer: {}", err),
65             CreationError::UnsupportedUsage { usage } => write!(
66                 fmt,
67                 "Failed to create buffer: Unsupported usage: {:?}",
68                 usage
69             ),
70         }
71     }
72 }
73 
74 impl std::error::Error for CreationError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>75     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
76         match self {
77             CreationError::OutOfMemory(err) => Some(err),
78             _ => None,
79         }
80     }
81 }
82 
83 /// Error creating a buffer view.
84 #[derive(Clone, Debug, PartialEq)]
85 pub enum ViewCreationError {
86     /// Out of either host or device memory.
87     OutOfMemory(device::OutOfMemory),
88 
89     /// Buffer view format is not supported.
90     UnsupportedFormat(Option<format::Format>),
91 }
92 
93 impl From<device::OutOfMemory> for ViewCreationError {
from(error: device::OutOfMemory) -> Self94     fn from(error: device::OutOfMemory) -> Self {
95         ViewCreationError::OutOfMemory(error)
96     }
97 }
98 
99 impl std::fmt::Display for ViewCreationError {
fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result100     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101         match self {
102             ViewCreationError::OutOfMemory(err) => {
103                 write!(fmt, "Failed to create buffer view: {}", err)
104             }
105             ViewCreationError::UnsupportedFormat(Some(format)) => write!(
106                 fmt,
107                 "Failed to create buffer view: Unsupported format {:?}",
108                 format
109             ),
110             ViewCreationError::UnsupportedFormat(None) => {
111                 write!(fmt, "Failed to create buffer view: Unspecified format")
112             }
113         }
114     }
115 }
116 
117 impl std::error::Error for ViewCreationError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>118     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
119         match self {
120             ViewCreationError::OutOfMemory(err) => Some(err),
121             _ => None,
122         }
123     }
124 }
125 
126 bitflags!(
127     /// Buffer usage flags.
128     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129     pub struct Usage: u32 {
130         ///
131         const TRANSFER_SRC  = 0x1;
132         ///
133         const TRANSFER_DST = 0x2;
134         ///
135         const UNIFORM_TEXEL = 0x4;
136         ///
137         const STORAGE_TEXEL = 0x8;
138         ///
139         const UNIFORM = 0x10;
140         ///
141         const STORAGE = 0x20;
142         ///
143         const INDEX = 0x40;
144         ///
145         const VERTEX = 0x80;
146         ///
147         const INDIRECT = 0x100;
148     }
149 );
150 
151 impl Usage {
152     /// Returns if the buffer can be used in transfer operations.
can_transfer(&self) -> bool153     pub fn can_transfer(&self) -> bool {
154         self.intersects(Usage::TRANSFER_SRC | Usage::TRANSFER_DST)
155     }
156 }
157 
158 bitflags!(
159     /// Buffer access flags.
160     ///
161     /// Access of buffers by the pipeline or shaders.
162     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
163     pub struct Access: u32 {
164         /// Read commands instruction for indirect execution.
165         const INDIRECT_COMMAND_READ = 0x1;
166         /// Read index values for indexed draw commands.
167         ///
168         /// See [`draw_indexed`](../command/trait.RawCommandBuffer.html#tymethod.draw_indexed)
169         /// and [`draw_indexed_indirect`](../command/trait.RawCommandBuffer.html#tymethod.draw_indexed_indirect).
170         const INDEX_BUFFER_READ = 0x2;
171         /// Read vertices from vertex buffer for draw commands in the [`VERTEX_INPUT`](
172         /// ../pso/struct.PipelineStage.html#associatedconstant.VERTEX_INPUT) stage.
173         const VERTEX_BUFFER_READ = 0x4;
174         ///
175         const UNIFORM_READ = 0x8;
176         ///
177         const SHADER_READ = 0x20;
178         ///
179         const SHADER_WRITE = 0x40;
180         ///
181         const TRANSFER_READ = 0x800;
182         ///
183         const TRANSFER_WRITE = 0x1000;
184         ///
185         const HOST_READ = 0x2000;
186         ///
187         const HOST_WRITE = 0x4000;
188         ///
189         const MEMORY_READ = 0x8000;
190         ///
191         const MEMORY_WRITE = 0x10000;
192     }
193 );
194 
195 /// Index buffer view for `bind_index_buffer`.
196 ///
197 /// Defines a buffer slice used for acquiring the indices on draw commands.
198 /// Indices are used to lookup vertex indices in the vertex buffers.
199 #[derive(Debug)]
200 pub struct IndexBufferView<'a, B: Backend> {
201     /// The buffer to bind.
202     pub buffer: &'a B::Buffer,
203     /// The subrange of the buffer.
204     pub range: SubRange,
205     /// The type of the table elements (`u16` or `u32`).
206     pub index_type: IndexType,
207 }
208