1#![warn(missing_debug_implementations)]
14#![warn(missing_copy_implementations)]
15
16use std::{
17 cmp::{Ord, Ordering},
18 convert::TryFrom,
19 error::Error,
20 fmt::Debug,
21};
22
23#[cfg(feature = "tracing")]
24#[macro_export]
25macro_rules! trace {
26 ($($tokens:tt)*) => {
27 tracing::trace!($($tokens)*)
28 };
29}
30
31#[cfg(feature = "tracing")]
32#[macro_export]
33macro_rules! debug {
34 ($($tokens:tt)*) => {
35 tracing::debug!($($tokens)*)
36 };
37}
38
39#[cfg(feature = "tracing")]
40#[macro_export]
41macro_rules! info {
42 ($($tokens:tt)*) => {
43 tracing::info!($($tokens)*)
44 };
45}
46
47#[cfg(feature = "tracing")]
48#[macro_export]
49macro_rules! warn {
50 ($($tokens:tt)*) => {
51 tracing::warn!($($tokens)*)
52 };
53}
54
55#[cfg(feature = "tracing")]
56#[macro_export]
57macro_rules! error {
58 ($($tokens:tt)*) => {
59 tracing::error!($($tokens)*)
60 };
61}
62
63#[cfg(not(feature = "tracing"))]
64#[macro_export]
65macro_rules! trace {
66 ($($e:expr),*) => {{ $(let _ = &$e;)* }};
67}
68
69#[cfg(not(feature = "tracing"))]
70#[macro_export]
71macro_rules! debug {
72 ($($e:expr),*) => {{ $( let _ = &$e;)* }};
73}
74
75#[cfg(not(feature = "tracing"))]
76#[macro_export]
77macro_rules! info {
78 ($($e:expr),*) => {{ $(let _ = &$e;)* }};
79}
80
81#[cfg(not(feature = "tracing"))]
82#[macro_export]
83macro_rules! warn {
84 ($($e:expr),*) => {{ $(let _ = &$e;)* }};
85}
86
87#[cfg(not(feature = "tracing"))]
88#[macro_export]
89macro_rules! error {
90 ($($e:expr),*) => {{ $(let _ = &$e;)* }};
91}
92
93pub mod backend;
94
95mod accel;
96mod access;
97mod buffer;
98mod cache;
99mod descriptor;
100mod dimensions;
101mod encode;
102mod fence;
103mod format;
104mod framebuffer;
105mod image;
106mod memory;
107mod physical;
108mod pipeline;
109mod queue;
110mod render_pass;
111mod repr;
112mod sampler;
113mod semaphore;
114mod shader;
115mod stage;
116mod surface;
117mod view;
118
119pub use self::{
120 accel::*,
121 access::*,
122 backend::{Device, Graphics},
123 buffer::*,
124 cache::*,
125 descriptor::*,
126 dimensions::*,
127 encode::*,
128 fence::*,
129 format::*,
130 framebuffer::*,
131 image::*,
132 memory::*,
133 physical::*,
134 pipeline::*,
135 queue::*,
136 render_pass::*,
137 repr::*,
138 sampler::*,
139 semaphore::*,
140 shader::*,
141 stage::*,
142 surface::*,
143 view::*,
144};
145
146pub use sierra_proc::{
147 binding_flags, format, graphics_pipeline_desc, shader_stages, swizzle, Descriptors, Pass,
148 PipelineInput, ShaderRepr,
149};
150
151#[doc(hidden)]
153pub use {arrayvec, bytemuck, scoped_arena, smallvec};
154
155#[derive(Clone, Copy, Debug, thiserror::Error, PartialEq, Eq)]
161#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
162#[error("Out of device memory")]
163pub struct OutOfMemory;
164
165#[derive(Clone, Copy, Debug, thiserror::Error, PartialEq, Eq)]
177#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
178#[error("Device lost")]
179pub struct DeviceLost;
180
181#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
183#[repr(transparent)]
184pub struct DeviceAddress(pub std::num::NonZeroU64);
185
186impl DeviceAddress {
187 pub fn offset(&mut self, offset: u64) -> DeviceAddress {
188 let value = self.0.get().checked_add(offset).unwrap();
189
190 DeviceAddress(unsafe { std::num::NonZeroU64::new_unchecked(value) })
191 }
192}
193
194#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
195#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
196pub enum IndexType {
197 U16,
198 U32,
199}
200
201impl IndexType {
202 pub fn size(&self) -> u8 {
203 match self {
204 IndexType::U16 => 2,
205 IndexType::U32 => 4,
206 }
207 }
208}
209
210#[derive(Debug, thiserror::Error)]
211pub enum CreateDeviceError<E: Error + 'static> {
212 #[error(transparent)]
213 OutOfMemory {
214 #[from]
215 source: OutOfMemory,
216 },
217
218 #[error("Non-existed families are requested")]
219 BadFamiliesRequested,
220
221 #[error(transparent)]
222 CannotFindRequeredQueues { source: E },
223
224 #[error("Failed to load functions")]
226 FunctionLoadFailed,
227}
228
229#[derive(Clone, Copy, Debug, thiserror::Error, PartialEq, Eq)]
231pub enum CreateBufferError {
232 #[error(transparent)]
233 OutOfMemory {
234 #[from]
235 source: OutOfMemory,
236 },
237
238 #[error("Buffer usage {usage:?} is unsupported")]
239 UnsupportedUsage { usage: BufferUsage },
240}
241
242#[derive(Clone, Copy, Debug, thiserror::Error)]
244pub enum MapError {
245 #[error(transparent)]
247 OutOfMemory {
248 #[from]
249 source: OutOfMemory,
250 },
251
252 #[error("Memory is not host-visible")]
254 NonHostVisible,
255
256 #[error("Memory is already mapped")]
258 AlreadyMapped,
259
260 #[error("Map failed for implementation specific reason")]
262 MapFailed,
263}
264
265#[doc(hidden)]
266pub trait OrdArith<T>: Copy {
267 fn cmp(self, rhs: T) -> Ordering;
268}
269
270impl<T> OrdArith<T> for T
271where
272 T: Ord + Copy,
273{
274 fn cmp(self, rhs: T) -> Ordering {
275 <T as Ord>::cmp(&self, &rhs)
276 }
277}
278
279impl OrdArith<u32> for usize {
280 fn cmp(self, rhs: u32) -> Ordering {
281 match u32::try_from(self) {
282 Ok(lhs) => Ord::cmp(&lhs, &rhs),
283 Err(_) => Ordering::Greater,
284 }
285 }
286}
287
288impl OrdArith<u64> for usize {
289 fn cmp(self, rhs: u64) -> Ordering {
290 match u64::try_from(self) {
291 Ok(lhs) => Ord::cmp(&lhs, &rhs),
292 Err(_) => Ordering::Greater,
293 }
294 }
295}
296
297impl OrdArith<u128> for usize {
298 fn cmp(self, rhs: u128) -> Ordering {
299 match u128::try_from(self) {
300 Ok(lhs) => Ord::cmp(&lhs, &rhs),
301 Err(_) => Ordering::Greater,
302 }
303 }
304}
305
306impl OrdArith<usize> for u32 {
307 fn cmp(self, rhs: usize) -> Ordering {
308 match u32::try_from(rhs) {
309 Ok(rhs) => Ord::cmp(&self, &rhs),
310 Err(_) => Ordering::Less,
311 }
312 }
313}
314
315impl OrdArith<usize> for u64 {
316 fn cmp(self, rhs: usize) -> Ordering {
317 match u64::try_from(rhs) {
318 Ok(rhs) => Ord::cmp(&self, &rhs),
319 Err(_) => Ordering::Less,
320 }
321 }
322}
323
324impl OrdArith<usize> for u128 {
325 fn cmp(self, rhs: usize) -> Ordering {
326 match u128::try_from(rhs) {
327 Ok(rhs) => Ord::cmp(&self, &rhs),
328 Err(_) => Ordering::Less,
329 }
330 }
331}
332
333impl OrdArith<u32> for u64 {
334 fn cmp(self, rhs: u32) -> Ordering {
335 Ord::cmp(&self, &u64::from(rhs))
336 }
337}
338
339impl OrdArith<u32> for u128 {
340 fn cmp(self, rhs: u32) -> Ordering {
341 Ord::cmp(&self, &u128::from(rhs))
342 }
343}
344
345impl OrdArith<u64> for u128 {
346 fn cmp(self, rhs: u64) -> Ordering {
347 Ord::cmp(&self, &u128::from(rhs))
348 }
349}
350
351#[doc(hidden)]
352pub fn arith_cmp<T>(lhs: impl OrdArith<T>, rhs: T) -> Ordering {
353 lhs.cmp(rhs)
354}
355
356#[doc(hidden)]
357pub fn arith_eq<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
358 lhs.cmp(rhs) == Ordering::Equal
359}
360
361#[doc(hidden)]
362pub fn arith_ne<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
363 lhs.cmp(rhs) != Ordering::Equal
364}
365
366#[doc(hidden)]
367pub fn arith_lt<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
368 lhs.cmp(rhs) == Ordering::Less
369}
370
371#[doc(hidden)]
372pub fn arith_gt<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
373 lhs.cmp(rhs) == Ordering::Greater
374}
375
376#[doc(hidden)]
377pub fn arith_le<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
378 lhs.cmp(rhs) != Ordering::Greater
379}
380
381#[doc(hidden)]
382pub fn arith_ge<T>(lhs: impl OrdArith<T>, rhs: T) -> bool {
383 lhs.cmp(rhs) != Ordering::Less
384}
385
386#[track_caller]
389pub fn out_of_host_memory() -> ! {
390 use std::alloc::{handle_alloc_error, Layout};
391
392 handle_alloc_error(unsafe { Layout::from_size_align_unchecked(1, 1) })
393}
394
395pub fn host_memory_space_overflow() -> ! {
398 panic!("Memory address space overflow")
399}
400
401fn assert_object<T: Debug + Send + Sync + 'static>() {}
402fn assert_error<T: Error + Send + Sync + 'static>() {}
403
404pub fn align_up(align_mask: u64, value: u64) -> Option<u64> {
406 Some(value.checked_add(align_mask)? & !align_mask)
407}
408
409pub fn align_down(align_mask: u64, value: u64) -> u64 {
411 value & !align_mask
412}
413
414#[macro_export]
415macro_rules! descriptor_set_layout_bindings {
416 ($($ty:ident $(($count:expr))? $(@$binding:literal)? for $($stages:ident),+ $($(| $flags:ident)+)?),*) => {
417 {
418 let mut binding = 0;
419 vec![
420 $({
421 $(binding = $binding + 1)?;
422 $crate::DescriptorSetLayoutBinding {
423 binding: binding - 1,
424 ty: $crate::DescriptorType::$ty,
425 count: 1 $(- 1 + $count)?,
426 stages: $($crate::ShaderStageFlags::$stages)|+,
427 flags: $crate::DescriptorBindingFlags::empty() $(| $crate::DescriptorBindingFlags::$flags)*,
428 }
429 },)*
430 ]
431 }
432 };
433}
434
435#[macro_export]
436macro_rules! descriptor_set_layout {
437 ($(|$flags:ident) *$($ty:ident $(($count:expr))? $(@$binding:literal)? for $($stages:ident)+ $($(| $bflags:ident)+)?),*) => {
438 $crate::DescriptorSetLayoutInfo {
439 flags: $crate::DescriptorSetLayoutFlags::empty() $(| $crate::DescriptorSetLayoutFlags::$flags)*,
440 bindings: descriptor_set_layout_bindings!($($ty $(@$binding)? $(* $count)? for $($stages)+ $($(| $bflags)+)?)*),
441 }
442 }
443}
444
445mod sealed {
446 #[doc(hidden)]
447 pub trait Sealed {}
448}
449
450trait IteratorExt: Iterator {
451 fn filter_min_by_key<B, F>(self, f: F) -> Option<Self::Item>
452 where
453 Self: Sized,
454 B: Ord,
455 F: FnMut(&Self::Item) -> Option<B>,
456 {
457 #[inline]
458 fn key<T, B>(mut f: impl FnMut(&T) -> Option<B>) -> impl FnMut(T) -> Option<(B, T)> {
459 move |x| Some((f(&x)?, x))
460 }
461
462 #[inline]
463 fn compare<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering {
464 x_p.cmp(y_p)
465 }
466
467 let (_, x) = self.filter_map(key(f)).min_by(compare)?;
468 Some(x)
469 }
470}
471
472impl<T> IteratorExt for T where T: Iterator {}