nc_renderer/
common.rs

1//
2// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30use rs_ctypes::*;
31use rs_math3d::*;
32
33use core::sync::atomic::*;
34use core::ops::{Deref, DerefMut};
35
36pub trait IntrusiveCounter {
37    fn increment(&mut self);
38    fn decrement(&mut self) -> isize;
39}
40
41#[repr(C)]
42pub struct IntrusivePtr<T : IntrusiveCounter + ?Sized> {
43    object  : *mut T,
44}
45
46impl<T: IntrusiveCounter> IntrusivePtr<T> {
47    pub fn new(mut t: T) -> Self {
48        t.increment();
49        let b = Box::new(t);
50        let r = Box::into_raw(b);
51        let s = Self { object: r };
52        s
53    }
54}
55
56impl<T: IntrusiveCounter + ?Sized> IntrusivePtr<T> {
57    pub fn as_ref(&self) -> *const T { self.object }
58    pub(crate) unsafe fn into_raw_mut(self) -> *mut T { let obj = self.object; std::mem::forget(self); obj }
59    pub(crate) unsafe fn from_raw_no_increment(raw: *mut T) -> Self { Self { object: raw } }
60    pub(crate) unsafe fn from_raw_increment(raw: *mut T) -> Self { (*raw).increment(); Self { object: raw } }
61}
62
63impl<T: IntrusiveCounter + ?Sized> Drop for IntrusivePtr<T> {
64    fn drop(&mut self) {
65        unsafe {
66            let rc = (*self.object).decrement();
67            if rc == 1 {
68                Box::from_raw(self.object);
69            }
70        }
71    }
72}
73
74impl<T: IntrusiveCounter + ?Sized> Clone for IntrusivePtr<T> {
75    fn clone(&self) -> Self {
76        unsafe { (*self.object).increment() };
77        Self { object : self.object }
78    }
79}
80
81impl<T: IntrusiveCounter + ?Sized> Deref for IntrusivePtr<T> {
82    type Target = T;
83
84    fn deref(&self) -> &Self::Target {
85        unsafe { &(*self.object) }
86    }
87}
88
89impl<T: IntrusiveCounter + ?Sized> DerefMut for IntrusivePtr<T> {
90    fn deref_mut(&mut self) -> &mut Self::Target {
91        unsafe { &mut (*self.object) }
92    }
93}
94
95impl<T: IntrusiveCounter + ?Sized> core::borrow::Borrow<T> for IntrusivePtr<T> {
96    fn borrow(&self) -> &T {
97        &**self
98    }
99}
100
101pub enum ResourceType {
102    DeviceBuffer,
103    Texture,
104    RenderTarget,
105    Shader,
106    Pipeline,
107    FrameBuffer,
108}
109
110#[repr(C)]
111pub struct Resource<Desc> {
112    res_type: ResourceType,
113    res_id  : usize,
114    desc    : Desc,
115    depends_on  : Option<IntrusivePtr<dyn Driver>>,   /// resources depend on drivers or other resources
116    rc      : AtomicIsize,
117}
118
119impl<Desc> Resource<Desc> {
120    pub(crate)  fn new(res_type: ResourceType, res_id: usize, desc: Desc, depends_on : Option<IntrusivePtr<dyn Driver>>) -> Self {
121        Self { res_type: res_type, res_id : res_id, desc: desc, depends_on: depends_on, rc: AtomicIsize::new(0) }
122    }
123    pub(crate)  fn res_id(&self) -> usize { self.res_id }
124    pub         fn desc(&self) -> &Desc { &self.desc }
125}
126
127impl<Desc> IntrusiveCounter for Resource<Desc> {
128    fn increment(&mut self) { self.rc.fetch_add(1, Ordering::SeqCst); }
129    fn decrement(&mut self) -> isize {
130        self.rc.fetch_sub(1, Ordering::SeqCst)
131    }
132}
133
134impl<Desc> Drop for Resource<Desc> {
135    fn drop(&mut self) {
136        match &mut self.depends_on {
137            Some(driver)    => driver.delete_resource(&self.res_type, self.res_id),
138            _ => panic!("No driver!")
139        }
140    }
141}
142
143////////////////////////////////////////////////////////////////////////////////
144/// Attributes
145////////////////////////////////////////////////////////////////////////////////
146
147pub trait AttributeDataTypeGetter {
148    fn get_attribute_type() -> VertexFormat;
149}
150
151// i8 type
152impl AttributeDataTypeGetter for i8 {
153    fn get_attribute_type() -> VertexFormat { VertexFormat::SByte }
154}
155
156impl AttributeDataTypeGetter for Vector2<i8> {
157    fn get_attribute_type() -> VertexFormat { VertexFormat::SByte2 }
158}
159
160impl AttributeDataTypeGetter for Vector3<i8> {
161    fn get_attribute_type() -> VertexFormat { VertexFormat::SByte3 }
162}
163
164impl AttributeDataTypeGetter for Vector4<i8> {
165    fn get_attribute_type() -> VertexFormat { VertexFormat::SByte4 }
166}
167
168// u8 type
169impl AttributeDataTypeGetter for u8 {
170    fn get_attribute_type() -> VertexFormat { VertexFormat::Byte }
171}
172
173impl AttributeDataTypeGetter for Vector2<u8> {
174    fn get_attribute_type() -> VertexFormat { VertexFormat::Byte2 }
175}
176
177impl AttributeDataTypeGetter for Vector3<u8> {
178    fn get_attribute_type() -> VertexFormat { VertexFormat::Byte3 }
179}
180
181impl AttributeDataTypeGetter for Vector4<u8> {
182    fn get_attribute_type() -> VertexFormat { VertexFormat::Byte4 }
183}
184
185// s16 type
186impl AttributeDataTypeGetter for i16 {
187    fn get_attribute_type() -> VertexFormat { VertexFormat::Short }
188}
189
190impl AttributeDataTypeGetter for Vector2<i16> {
191    fn get_attribute_type() -> VertexFormat { VertexFormat::Short2 }
192}
193
194impl AttributeDataTypeGetter for Vector3<i16> {
195    fn get_attribute_type() -> VertexFormat { VertexFormat::Short3 }
196}
197
198impl AttributeDataTypeGetter for Vector4<i16> {
199    fn get_attribute_type() -> VertexFormat { VertexFormat::Short4 }
200}
201
202// f32 type
203impl AttributeDataTypeGetter for f32 {
204    fn get_attribute_type() -> VertexFormat { VertexFormat::Float }
205}
206
207impl AttributeDataTypeGetter for Vector2<f32> {
208    fn get_attribute_type() -> VertexFormat { VertexFormat::Float2 }
209}
210
211impl AttributeDataTypeGetter for Vector3<f32> {
212    fn get_attribute_type() -> VertexFormat { VertexFormat::Float3 }
213}
214
215impl AttributeDataTypeGetter for Vector4<f32> {
216    fn get_attribute_type() -> VertexFormat { VertexFormat::Float4 }
217}
218
219// i32 type
220impl AttributeDataTypeGetter for i32 {
221    fn get_attribute_type() -> VertexFormat { VertexFormat::Int }
222}
223
224impl AttributeDataTypeGetter for Vector2<i32> {
225    fn get_attribute_type() -> VertexFormat { VertexFormat::Int2 }
226}
227
228impl AttributeDataTypeGetter for Vector3<i32> {
229    fn get_attribute_type() -> VertexFormat { VertexFormat::Int3 }
230}
231
232impl AttributeDataTypeGetter for Vector4<i32> {
233    fn get_attribute_type() -> VertexFormat { VertexFormat::Int4 }
234}
235
236// u32 type
237impl AttributeDataTypeGetter for u32 {
238    fn get_attribute_type() -> VertexFormat { VertexFormat::UInt }
239}
240
241impl AttributeDataTypeGetter for Vector2<u32> {
242    fn get_attribute_type() -> VertexFormat { VertexFormat::UInt2 }
243}
244
245impl AttributeDataTypeGetter for Vector3<u32> {
246    fn get_attribute_type() -> VertexFormat { VertexFormat::UInt3 }
247}
248
249impl AttributeDataTypeGetter for Vector4<u32> {
250    fn get_attribute_type() -> VertexFormat { VertexFormat::UInt4 }
251}
252
253
254// matrix type
255impl AttributeDataTypeGetter for Matrix2<f32> {
256    fn get_attribute_type() -> VertexFormat { VertexFormat::Float2x2 }
257}
258
259impl AttributeDataTypeGetter for Matrix3<f32> {
260    fn get_attribute_type() -> VertexFormat { VertexFormat::Float3x3 }
261}
262
263impl AttributeDataTypeGetter for Matrix4<f32> {
264    fn get_attribute_type() -> VertexFormat { VertexFormat::Float4x4 }
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Uniforms
269////////////////////////////////////////////////////////////////////////////////
270
271pub trait UniformDataTypeGetter {
272    fn get_uniform_type() -> UniformDataType;
273}
274
275impl UniformDataTypeGetter for u32 {
276    fn get_uniform_type() -> UniformDataType { UniformDataType::UInt }
277}
278
279impl UniformDataTypeGetter for Vector2<u32> {
280    fn get_uniform_type() -> UniformDataType { UniformDataType::UInt2 }
281}
282
283impl UniformDataTypeGetter for Vector3<u32> {
284    fn get_uniform_type() -> UniformDataType { UniformDataType::UInt3 }
285}
286
287impl UniformDataTypeGetter for Vector4<u32> {
288    fn get_uniform_type() -> UniformDataType { UniformDataType::UInt4 }
289}
290
291impl UniformDataTypeGetter for i32 {
292    fn get_uniform_type() -> UniformDataType { UniformDataType::Int }
293}
294
295impl UniformDataTypeGetter for Vector2<i32> {
296    fn get_uniform_type() -> UniformDataType { UniformDataType::Int2 }
297}
298
299impl UniformDataTypeGetter for Vector3<i32> {
300    fn get_uniform_type() -> UniformDataType { UniformDataType::Int3 }
301}
302
303impl UniformDataTypeGetter for Vector4<i32> {
304    fn get_uniform_type() -> UniformDataType { UniformDataType::Int4 }
305}
306
307impl UniformDataTypeGetter for f32 {
308    fn get_uniform_type() -> UniformDataType { UniformDataType::Float }
309}
310
311impl UniformDataTypeGetter for Vector2<f32> {
312    fn get_uniform_type() -> UniformDataType { UniformDataType::Float2 }
313}
314
315impl UniformDataTypeGetter for Vector3<f32> {
316    fn get_uniform_type() -> UniformDataType { UniformDataType::Float3 }
317}
318
319impl UniformDataTypeGetter for Vector4<f32> {
320    fn get_uniform_type() -> UniformDataType { UniformDataType::Float4 }
321}
322
323impl UniformDataTypeGetter for Matrix2<f32> {
324    fn get_uniform_type() -> UniformDataType { UniformDataType::Float2x2 }
325}
326
327impl UniformDataTypeGetter for Matrix3<f32> {
328    fn get_uniform_type() -> UniformDataType { UniformDataType::Float3x3 }
329}
330
331impl UniformDataTypeGetter for Matrix4<f32> {
332    fn get_uniform_type() -> UniformDataType { UniformDataType::Float4x4 }
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// Macros
337////////////////////////////////////////////////////////////////////////////////
338#[macro_export]
339macro_rules! offset_of {
340    ($Struct:path, $field:ident) => ({
341        // Using a separate function to minimize unhygienic hazards
342        // (e.g. unsafety of #[repr(packed)] field borrows).
343        // Uncomment `const` when `const fn`s can juggle pointers.
344        /*const*/ fn offset() -> usize {
345            let u = std::mem::MaybeUninit::<$Struct>::uninit();
346            // Use pattern-matching to avoid accidentally going through Deref.
347            let &$Struct { $field: ref f, .. } = unsafe { &*u.as_ptr() };
348            let o = (f as *const _ as usize).wrapping_sub(&u as *const _ as usize);
349            // Triple check that we are within `u` still.
350            assert!((0..=std::mem::size_of_val(&u)).contains(&o));
351            o
352        }
353        offset()
354    })
355}
356
357#[macro_export]
358macro_rules! render_data {
359    () => {};
360    (vertex $name:ident { $($field_name:ident: $field_type:ty,)* }) => {
361        #[repr(C)]
362        #[derive(Debug, Copy, Clone)]
363        struct $name {
364            $($field_name: $field_type,)*
365        }
366
367        impl $crate::VertexTrait for $name {
368            // This is purely an example—not a good one.
369            fn get_attribute_descriptors() -> Vec<$crate::VertexAttributeDesc> {
370                vec![$($crate::VertexAttributeDesc::new(stringify!($field_name).to_string(), <$field_type>::get_attribute_type(), $crate::offset_of!($name, $field_name))),*]
371            }
372
373            fn get_attribute_names() -> Vec<String> {
374                vec![$(stringify!($field_name).to_string()),*]
375            }
376
377            fn stride() -> usize {
378                core::mem::size_of::<Self>()
379            }
380        }
381    };
382
383    (vertex $name:ident { $($field_name:ident: $field_type:ty,)* } $($e:tt)*) => {
384        $crate::render_data! { vertex $name {
385            $($field_name: $field_type,)*
386        } }
387        $crate::render_data! { $($e)* }
388    };
389
390    (pub vertex $name:ident { $($field_name:ident: $field_type:ty,)* }) => {
391        #[repr(C)]
392        #[derive(Debug, Copy, Clone)]
393        pub struct $name {
394            $($field_name: $field_type,)*
395        }
396
397        impl $crate::renderer::VertexTrait for $name {
398            // This is purely an example—not a good one.
399            fn get_attribute_descriptors() -> Vec<$crate::VertexAttributeDesc> {
400                vec![$($crate::VertexAttributeDesc::new(stringify!($field_name).to_string(), <$field_type>::get_attribute_type(), $crate::offset_of!($name, $field_name))),*]
401            }
402
403            fn get_attribute_names() -> Vec<String> {
404                vec![$(stringify!($field_name).to_string()),*]
405            }
406
407            fn stride() -> usize {
408                core::mem::size_of::<Self>()
409            }
410        }
411    };
412
413    (pub vertex $name:ident { $($field_name:ident: $field_type:ty,)* } $($e:tt)*) => {
414        $crate::render_data! { pub vertex $name {
415            $($field_name: $field_type,)*
416        } }
417        $crate::render_data! { $($e)* }
418    };
419
420    (uniforms $name:ident {
421        $($field_name:ident: $field_type:ty,)*
422    }) => {
423        #[repr(C)]
424        #[derive(Debug, Copy, Clone)]
425        struct $name {
426            $($field_name: $field_type,)*
427        }
428
429        impl $crate::UniformBlockTrait for $name {
430            // This is purely an example—not a good one.
431            fn get_uniform_descriptors() -> Vec<UniformDataDesc> {
432                vec![$(UniformDataDesc::new(stringify!($field_name).to_string(), <$field_type>::get_uniform_type(), 1, $crate::offset_of!($name, $field_name))),*]
433            }
434
435            fn get_uniform_names() -> Vec<String> {
436                vec![$(stringify!($field_name).to_string()),*]
437            }
438        }
439    };
440
441    (uniforms $name:ident {
442        $($field_name:ident: $field_type:ty,)*
443    } $($e:tt)*) => {
444        $crate::render_data! { uniforms $name {
445            $($field_name: $field_type,)*
446        } }
447        $crate::render_data! { $($e)* }
448    };
449}
450
451////////////////////////////////////////////////////////////////////////////////
452/// VertexAttributeDesc
453////////////////////////////////////////////////////////////////////////////////
454
455#[derive(Clone)]
456pub enum VertexFormat {
457    Byte,
458    Byte2,
459    Byte3,
460    Byte4,
461
462    SByte,
463    SByte2,
464    SByte3,
465    SByte4,
466
467    Short,
468    Short2,
469    Short3,
470    Short4,
471
472    Int,
473    Int2,
474    Int3,
475    Int4,
476
477    UInt,
478    UInt2,
479    UInt3,
480    UInt4,
481
482    Float,
483    Float2,
484    Float3,
485    Float4,
486
487    Float2x2,
488    Float3x3,
489    Float4x4,
490}
491
492
493#[derive(Clone)]
494pub struct VertexAttributeDesc {
495    name        : String,
496    format      : VertexFormat,
497    offset      : usize,
498}
499
500impl VertexAttributeDesc {
501    pub fn new(name: String, format: VertexFormat, offset: usize) -> Self {
502        Self {
503            name        : name,
504            format      : format,
505            offset      : offset,
506        }
507    }
508
509    pub fn name(&self)      -> &String  { &self.name        }
510    pub fn format(&self)    -> VertexFormat   { self.format.clone() }
511    pub fn offset(&self)    -> usize    { self.offset       }
512}
513
514pub trait VertexTrait {
515    fn get_attribute_descriptors() -> Vec<VertexAttributeDesc>;
516    fn get_attribute_names() -> Vec<String>;
517    fn stride() -> usize;
518}
519
520
521
522////////////////////////////////////////////////////////////////////////////////
523/// UniformBlock
524////////////////////////////////////////////////////////////////////////////////
525
526#[derive(Clone)]
527pub enum UniformDataType {
528    UInt,
529    UInt2,
530    UInt3,
531    UInt4,
532    Int,
533    Int2,
534    Int3,
535    Int4,
536    Float,
537    Float2,
538    Float3,
539    Float4,
540    Float2x2,
541    Float3x3,
542    Float4x4,
543}
544
545#[derive(Clone)]
546pub struct UniformDesc {
547    name        : String,
548    format      : UniformDataType,
549    count       : usize,
550}
551
552impl UniformDesc {
553    pub fn new(name: String, format: UniformDataType, count: usize) -> Self { Self { name: name, format: format, count: count } }
554    pub fn name(&self)      -> &str     { self.name.as_str() }
555    pub fn format(&self)    -> UniformDataType { self.format.clone() }
556    pub fn count(&self)     -> usize    { self.count }
557}
558
559#[derive(Clone)]
560pub struct UniformDataDesc {
561    pub desc        : UniformDesc,
562    pub offset      : usize,
563}
564
565impl UniformDataDesc {
566    pub fn new(name: String, format: UniformDataType, count: usize, offset: usize) -> Self { Self { desc: UniformDesc::new(name, format, count), offset: offset } }
567    pub fn offset(&self)    -> usize    { self.offset }
568    pub fn desc(&self)      -> &UniformDesc   { &self.desc }
569}
570
571pub trait UniformBlockTrait {
572    fn get_uniform_descriptors() -> Vec<UniformDataDesc>;
573    fn get_uniform_names() -> Vec<String>;
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Buffers
578////////////////////////////////////////////////////////////////////////////////
579
580pub trait Payload {
581    fn ptr(&self) -> *const u8;
582    fn size(&self) -> usize;
583}
584
585impl<T> Payload for Vec<T> {
586    fn ptr(&self) -> *const u8 { self.as_ptr() as *const u8 }
587    fn size(&self) -> usize { ::core::mem::size_of::<T>() * self.len() }
588}
589
590impl<T> Payload for &[T] {
591    fn ptr(&self) -> *const u8 { self.as_ptr() as *const u8 }
592    fn size(&self) -> usize { ::core::mem::size_of::<T>() * self.len() }
593}
594
595pub enum Usage {
596    Static(Box<dyn Payload>),
597    Dynamic(usize),
598    Streamed(usize),
599}
600
601impl Usage {
602    // pub fn new_static<T>(data: &Vec<T>) -> Usage {
603    //     let p = data.as_ptr();
604    //     let nd = p as *const u8;
605    //     Self::Static(nd, data.len() * std::mem::size_of::<T>())
606    // }
607
608    pub fn new_dynamic<T>(len: usize) -> Usage {
609        Self::Dynamic(len * std::mem::size_of::<T>())
610    }
611
612    pub fn new_streamed<T>(len: usize) -> Usage {
613        Self::Dynamic(len * std::mem::size_of::<T>())
614    }
615
616    pub fn size(&self) -> usize {
617        match self {
618            Usage::Static(b)        => b.size(),
619            Usage::Dynamic(s)       => *s,
620            Usage::Streamed(s)      => *s,
621        }
622    }
623}
624
625
626pub struct DeviceBufferMapping {
627    pub ptr     : *mut u8,
628    pub offset  : usize,
629    pub size    : usize,
630    pub buff    : DeviceBufferPtr,
631}
632
633
634
635pub enum DeviceBufferDesc {
636    Vertex(Usage),
637    Index(Usage),
638    Pixel(Usage),
639}
640
641impl DeviceBufferDesc {
642    pub fn size(&self) -> usize {
643        match self {
644            Self::Vertex(u) |
645            Self::Index(u)  |
646            Self::Pixel(u)  => u.size(),
647        }
648    }
649}
650
651pub type DeviceBuffer       = Resource<DeviceBufferDesc>;
652pub type DeviceBufferPtr    = IntrusivePtr<DeviceBuffer>;
653
654////////////////////////////////////////////////////////////////////////////////
655/// ImageDesc
656////////////////////////////////////////////////////////////////////////////////
657
658#[derive(Clone, Copy)]
659pub enum WrapMode {
660    Repeat,
661    ClampToEdge,
662    ClampToBorder,
663    MirroredRepeat,
664}
665
666#[derive(Clone)]
667pub struct PixelChannel {
668    pub size    : usize,
669    pub wrap    : WrapMode,
670}
671
672impl PixelChannel {
673    pub fn default(size: usize) -> Self {
674        Self {
675            size    : size,
676            wrap    : WrapMode::Repeat,
677        }
678    }
679
680    pub fn resize(mut self, size: usize) -> Self {
681        self.size   = size;
682        self
683    }
684
685    pub fn with_wrap(mut self, wrap: WrapMode) -> Self {
686        self.wrap   = wrap;
687        self
688    }
689}
690
691#[derive(Clone)]
692pub enum SamplerType {
693    Sampler2D    (PixelChannel, PixelChannel),
694}
695
696#[derive(Clone, Debug)]
697pub enum Filter {
698    Nearest,
699    Linear,
700    NearestMipmapNearest,
701    NearestMipmapLinear,
702    LinearMipmapNearest,
703    LinearMipmapLinear,
704}
705
706#[derive(Clone, Debug)]
707pub enum PixelFormat {
708    RGB8U,
709    RGBA8U,
710    R8U,
711    RGB32U,
712    RGBA32U,
713    R32U,
714
715    RGB32F,
716    RGBA32F,
717    R32F,
718
719    D16,
720    D32,
721    D24S8,
722    D32S8,
723
724    RGB8(MinMagFilter),
725    RGBA8(MinMagFilter),
726    R8(MinMagFilter),
727}
728
729#[derive(Clone, Debug)]
730pub struct MinMagFilter {
731    pub min_filter  : Filter,
732    pub mag_filter  : Filter,
733}
734
735impl MinMagFilter {
736    pub fn default() -> Self {
737        Self {
738            min_filter  : Filter::Nearest,
739            mag_filter  : Filter::Nearest,
740        }
741    }
742
743    pub fn with_min_filter(mut self, filter: Filter) -> Self {
744        self.min_filter = filter;
745        self
746    }
747
748    pub fn with_mag_filter(mut self, filter: Filter) -> Self {
749        self.mag_filter = filter;
750        self
751    }
752}
753
754#[derive(Debug)]
755pub enum OrigSurfaceType {
756    UInt,
757    Float,
758}
759
760pub enum OrigSurfaceClass {
761    Color,
762    Depth,
763}
764
765impl PixelFormat {
766    pub fn to_orig_surface_type(&self) -> OrigSurfaceType {
767        match self {
768            PixelFormat::RGB8U => OrigSurfaceType::UInt,
769            PixelFormat::RGBA8U => OrigSurfaceType::UInt,
770            PixelFormat::R8U => OrigSurfaceType::UInt,
771            PixelFormat::RGB32U => OrigSurfaceType::UInt,
772            PixelFormat::RGBA32U => OrigSurfaceType::UInt,
773            PixelFormat::R32U => OrigSurfaceType::UInt,
774
775            PixelFormat::RGB32F => OrigSurfaceType::Float,
776            PixelFormat::RGBA32F => OrigSurfaceType::Float,
777            PixelFormat::R32F => OrigSurfaceType::Float,
778            PixelFormat::D16 => OrigSurfaceType::Float,
779            PixelFormat::D32 => OrigSurfaceType::Float,
780            PixelFormat::D24S8 => OrigSurfaceType::Float,
781            PixelFormat::D32S8 => OrigSurfaceType::Float,
782            PixelFormat::RGB8(_) => OrigSurfaceType::Float,
783            PixelFormat::RGBA8(_) => OrigSurfaceType::Float,
784            PixelFormat::R8(_) => OrigSurfaceType::Float,
785        }
786    }
787}
788
789#[derive(Clone)]
790pub struct SamplerDesc {
791    pub image_type  : SamplerType,
792    pub mip_maps    : usize,
793    pub pixel_format: PixelFormat,
794}
795
796impl SamplerDesc {
797    pub fn default(width: usize, height: usize) -> Self {
798        Self {
799            image_type  : SamplerType::Sampler2D(PixelChannel::default(width), PixelChannel::default(height)),
800            mip_maps    : 0,
801            pixel_format: PixelFormat::RGBA8U,
802        }
803    }
804
805    pub fn with_wrap_mode(mut self, wrap: WrapMode) -> Self {
806        let image_type =
807            match self.image_type {
808                SamplerType::Sampler2D(mut w, mut h) => {
809                    w.wrap  = wrap;
810                    h.wrap  = wrap;
811                    SamplerType::Sampler2D(w, h)
812                }
813            };
814        self.image_type = image_type;
815        self
816    }
817
818    pub fn with_pixel_format(mut self, pf: PixelFormat) -> Self {
819        self.pixel_format   = pf;
820        self
821    }
822
823    pub fn with_mip_maps(mut self, levels: usize) -> Self {
824        self.mip_maps   = levels;
825        self
826    }
827
828    pub fn width(&self) -> usize {
829        match self.image_type {
830            SamplerType::Sampler2D(PixelChannel { size, wrap: _ }, _) => size,
831            _ => panic!("no width!")
832        }
833    }
834
835    pub fn height(&self) -> usize {
836        match self.image_type {
837            SamplerType::Sampler2D(_, PixelChannel { size, wrap: _ }) => size,
838            _ => panic!("no height!")
839        }
840    }
841
842}
843pub struct TextureDesc {
844    pub sampler_desc    : SamplerDesc,
845    pub payload         : Option<Box<dyn Payload>>
846}
847
848pub struct RenderTargetDesc {
849    pub sampler_desc    : SamplerDesc,
850    pub sample_count    : usize
851}
852
853pub type Texture    = Resource<TextureDesc>;
854pub type TexturePtr = IntrusivePtr<Texture>;
855
856pub type RenderTarget       = Resource<RenderTargetDesc>;
857pub type RenderTargetPtr    = IntrusivePtr<RenderTarget>;
858
859////////////////////////////////////////////////////////////////////////////////
860/// ShaderDesc
861////////////////////////////////////////////////////////////////////////////////
862#[derive(Clone)]
863pub struct ShaderDesc {
864    pub vertex_shader       : String,
865    pub pixel_shader        : String,
866
867    pub vertex_attributes   : Vec<Vec<String>>,
868    pub vertex_uniforms     : Vec<String>,
869    pub vertex_surfaces     : Vec<String>,
870
871    pub pixel_uniforms      : Vec<String>,
872    pub pixel_surfaces      : Vec<String>,
873}
874
875pub type Shader     = Resource<ShaderDesc>;
876pub type ShaderPtr  = IntrusivePtr<Shader>;
877
878////////////////////////////////////////////////////////////////////////////////
879/// Binding
880////////////////////////////////////////////////////////////////////////////////
881#[derive(Clone, Eq, PartialEq)]
882pub enum IndexType {
883    None,
884    UInt16,
885    UInt32,
886}
887
888pub trait IndexTypeTrait {
889    fn to_index_type() -> IndexType;
890}
891
892impl IndexTypeTrait for u16 {
893    fn to_index_type() -> IndexType { IndexType::UInt16 }
894}
895
896impl IndexTypeTrait for u32 {
897    fn to_index_type() -> IndexType { IndexType::UInt32 }
898}
899
900#[derive(Clone)]
901pub struct Bindings {
902    pub vertex_buffers  : Vec<DeviceBufferPtr>,
903    pub index_buffer    : Option<DeviceBufferPtr>,
904
905    pub vertex_images   : Vec<TexturePtr>,
906    pub pixel_images    : Vec<TexturePtr>,
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// PipelineDesc
911////////////////////////////////////////////////////////////////////////////////
912#[derive(Clone)]
913pub enum PrimitiveType {
914    Points,
915    Lines,
916    LineStrip,
917    Triangles,
918    TriangleStrip,
919}
920
921#[derive(Clone)]
922pub enum CullMode {
923    Winding,
924    None,
925}
926
927#[derive(Clone)]
928pub enum FaceWinding {
929    CCW,
930    CW,
931}
932
933#[derive(Clone)]
934pub struct VertexBufferLayout {
935    pub buffer_id           : usize,
936    pub vertex_attributes   : Vec<VertexAttributeDesc>,
937    pub stride              : usize,
938    pub divisor             : usize,
939}
940
941#[derive(Clone)]
942pub enum BlendFactor {
943    Zero,
944    One,
945
946    SrcColor,
947    OneMinusSrcColor,
948    SrcAlpha,
949    OneMinusSrcAlpha,
950
951    DstColor,
952    OneMinusDstColor,
953    DstAlpha,
954    OneMinusDstAlpha,
955
956    SrcAlphaSaturate,
957    ConstantColor,
958    OneMinusConstantColor,
959    ConstantAlpha,
960    OneMinusConstantAlpha,
961}
962
963
964#[derive(Clone)]
965pub struct Blend {
966    pub src_factor_rgb      : BlendFactor,
967    pub src_factor_alpha    : BlendFactor,
968
969    pub dst_factor_rgb      : BlendFactor,
970    pub dst_factor_alpha    : BlendFactor,
971}
972
973impl Blend {
974    pub fn default() -> Self {
975        Self {
976            src_factor_rgb          : BlendFactor::One,
977            src_factor_alpha        : BlendFactor::One,
978
979            dst_factor_rgb          : BlendFactor::OneMinusSrcAlpha,
980            dst_factor_alpha        : BlendFactor::OneMinusSrcAlpha,
981        }
982    }
983}
984
985#[derive(Clone)]
986pub enum BlendOp {
987    None,
988    Add(Blend),
989    Subtract(Blend),
990    ReverseSubtract(Blend),
991}
992
993
994#[derive(Clone)]
995pub struct PipelineDesc {
996    pub primitive_type      : PrimitiveType,
997    pub shader              : ShaderPtr,
998
999    // layout
1000    pub buffer_layouts      : Vec<VertexBufferLayout>,
1001
1002    //
1003    pub uniform_descs       : Vec<UniformDataDesc>,
1004    pub index_type          : IndexType,
1005
1006    pub face_winding        : FaceWinding,
1007    pub cull_mode           : CullMode,
1008
1009    pub depth_write         : bool,
1010    pub depth_test          : bool,
1011
1012    pub blend               : BlendOp,
1013}
1014
1015pub type Pipeline   = Resource<PipelineDesc>;
1016pub type PipelinePtr= IntrusivePtr<Pipeline>;
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// Pass
1020////////////////////////////////////////////////////////////////////////////////
1021#[derive(Clone)]
1022pub enum ColorPassAction {
1023    Clear(Color4b),
1024    Previous,
1025}
1026
1027#[derive(Clone)]
1028pub enum DepthPassAction {
1029    Clear(f32),
1030    Previous,
1031}
1032
1033#[derive(Clone)]
1034pub enum SurfaceAttachment {
1035    Texture(TexturePtr),
1036    RenderTarget(RenderTargetPtr)
1037}
1038
1039impl SurfaceAttachment {
1040    pub fn pixel_format(&self) -> PixelFormat {
1041        match self {
1042            SurfaceAttachment::Texture(tex) => tex.desc.sampler_desc.pixel_format.clone(),
1043            SurfaceAttachment::RenderTarget(rt) => rt.desc.sampler_desc.pixel_format.clone(),
1044        }
1045    }
1046}
1047
1048#[derive(Clone)]
1049pub struct FrameBufferDesc {
1050    pub color_attachements          : [Option<SurfaceAttachment>; 4],
1051    pub depth_stencil_attachement   : SurfaceAttachment,
1052}
1053
1054pub type FrameBuffer    = Resource<FrameBufferDesc>;
1055pub type FrameBufferPtr = IntrusivePtr<FrameBuffer>;
1056
1057pub struct Pass {
1058    pub width           : usize,
1059    pub height          : usize,
1060    pub frame_buffer    : Option<FrameBufferPtr>,
1061    pub color_actions   : [ColorPassAction; 4],
1062    pub depth_action    : DepthPassAction,
1063}
1064
1065////////////////////////////////////////////////////////////////////////////////
1066/// Readback surface
1067////////////////////////////////////////////////////////////////////////////////
1068pub enum ReadbackPayload {
1069    RGB32U(Vec<Vector3<u32>>),
1070    RGBA32U(Vec<Vector4<u32>>),
1071    R32U(Vec<u32>),
1072
1073    RGB32F(Vec<Vec3f>),
1074    RGBA32F(Vec<Vec4f>),
1075    R32F(Vec<f32>),
1076
1077    Depth(Vec<f32>),
1078}
1079
1080pub enum ReadbackError {
1081    NoReadbackFromRenderTarget,
1082    RectOutOfBound,
1083}
1084
1085pub enum ReadbackResult {
1086    Ok(ReadbackPayload),
1087    Error(ReadbackError)
1088}
1089
1090////////////////////////////////////////////////////////////////////////////////
1091/// Capabilities
1092////////////////////////////////////////////////////////////////////////////////
1093pub struct DriverCaps {
1094    pub max_2d_surface_dimension    : Dimensioni,
1095}
1096
1097////////////////////////////////////////////////////////////////////////////////
1098/// Driver
1099////////////////////////////////////////////////////////////////////////////////
1100pub trait Driver : IntrusiveCounter {
1101    fn get_caps(&self) -> &DriverCaps;
1102    fn create_device_buffer(&mut self, desc: DeviceBufferDesc) -> Option<DeviceBufferPtr>;
1103    fn create_texture(&mut self, desc: TextureDesc) -> Option<TexturePtr>;
1104    fn create_render_target(&mut self, desc: RenderTargetDesc) -> Option<RenderTargetPtr>;
1105    fn create_shader(&mut self, desc: ShaderDesc) -> Option<ShaderPtr>;
1106    fn create_pipeline(&mut self, desc: PipelineDesc) -> Option<PipelinePtr>;
1107    fn create_frame_buffer(&mut self, desc: FrameBufferDesc) -> Option<FrameBufferPtr>;
1108
1109    fn delete_resource(&mut self, resource_type: &ResourceType, res_id: usize);
1110
1111    fn update_device_buffer(&mut self, dev_buf: &mut DeviceBufferPtr, offset: usize, pl: &dyn Payload);
1112    fn update_texture(&mut self, dev_buf: &mut TexturePtr, pl: Box<dyn Payload>);
1113
1114    fn begin_pass(&mut self, pass: &Pass);
1115    fn end_pass(&mut self);
1116
1117    fn set_viewport(&mut self, x: u32, y: u32, w: u32, h: u32);
1118    fn set_scissor(&mut self, x: u32, y: u32, w: u32, h: u32);
1119
1120    fn draw(&mut self, pipe: &Pipeline, bindings: &Bindings, uniforms: *const c_void, prim_count: u32, instance_count: u32);
1121
1122    fn read_back(&mut self, surface: &TexturePtr, x: u32, y: u32, w: u32, h: u32) -> Option<ReadbackPayload>;
1123}
1124
1125pub type DriverPtr = IntrusivePtr<dyn Driver>;
1126
1127
1128#[cfg(test)]
1129mod tests {
1130    use super::*;
1131
1132    struct InTest {
1133        s: String,
1134        r: core::sync::atomic::AtomicIsize,
1135    }
1136
1137    impl IntrusiveCounter for InTest {
1138        fn increment(&mut self) { self.r.fetch_add(1, Ordering::SeqCst); }
1139        fn decrement(&mut self) -> isize {
1140            self.r.fetch_sub(1, Ordering::SeqCst)
1141        }
1142    }
1143
1144    impl Drop for InTest {
1145        fn drop(&mut self) {}
1146    }
1147
1148    #[test]
1149    fn test_intrusive() {
1150        let it = InTest { s: String::from("Hello World"), r : core::sync::atomic::AtomicIsize::new(0) };
1151        let p = IntrusivePtr::new(it);
1152        format!("r: {}", p.s);
1153    }
1154}