embree_rs/
buffer.rs

1use std::marker::PhantomData;
2use std::{mem, ptr};
3use std::ops::{Index, IndexMut};
4
5use device::Device;
6use sys::*;
7use BufferType;
8
9#[derive(Copy, Clone)]
10struct BufferAttachment {
11    geom: RTCGeometry,
12    buf_type: BufferType,
13    slot: u32,
14}
15
16impl BufferAttachment {
17    fn none() -> BufferAttachment {
18        BufferAttachment {
19            geom: ptr::null_mut(),
20            buf_type: BufferType::VERTEX,
21            slot: std::u32::MAX,
22        }
23    }
24    fn is_attached(&self) -> bool {
25        self.geom != ptr::null_mut()
26    }
27}
28
29// TODO: To handle this nicely for sharing/re-using/changing buffer views
30// we basically need an API/struct for making buffer views of existing
31// larger buffers.
32pub struct Buffer<'a, T> {
33    device: &'a Device,
34    pub(crate) handle: RTCBuffer,
35    // TODO: We need a list of RTCGeometry handles
36    // that we're attached to to mark buffers as updated on
37    // the geometries.
38    bytes: usize,
39    attachment: BufferAttachment,
40    marker: PhantomData<T>,
41}
42
43impl<'a, T> Buffer<'a, T> {
44    /// Allocate a buffer with some raw capacity in bytes
45    pub fn raw(device: &'a Device, bytes: usize) -> Buffer<'a, T> {
46        // Pad to a multiple of 16 bytes
47        let bytes = if bytes % 16 == 0 { bytes } else { bytes + bytes / 16};
48        Buffer {
49            device: device,
50            handle: unsafe { rtcNewBuffer(device.handle, bytes) },
51            bytes: bytes,
52            attachment: BufferAttachment::none(),
53            marker: PhantomData,
54        }
55    }
56    pub fn new(device: &'a Device, len: usize) -> Buffer<'a, T> {
57        let mut bytes = len * mem::size_of::<T>();
58        // Pad to a multiple of 16 bytes
59        bytes = if bytes % 16 == 0 { bytes } else { bytes + bytes / 16};
60        Buffer {
61            device: device,
62            handle: unsafe { rtcNewBuffer(device.handle, bytes) },
63            bytes: bytes,
64            attachment: BufferAttachment::none(),
65            marker: PhantomData,
66        }
67    }
68    pub fn map(&mut self) -> MappedBuffer<'a, T> {
69        let len = self.bytes / mem::size_of::<T>();
70        let slice = unsafe { rtcGetBufferData(self.handle) as *mut T };
71        MappedBuffer {
72            buffer: PhantomData,
73            attachment: self.attachment,
74            slice: slice,
75            len: len,
76        }
77    }
78    pub(crate) fn set_attachment(&mut self, geom: RTCGeometry,
79                          buf_type: BufferType, slot: u32)
80    {
81        self.attachment.geom = geom;
82        self.attachment.buf_type = buf_type;
83        self.attachment.slot = slot;
84    }
85}
86
87impl<'a, T> Drop for Buffer<'a, T> {
88    fn drop(&mut self) {
89        unsafe {
90            rtcReleaseBuffer(self.handle);
91        }
92    }
93}
94
95unsafe impl<'a, T> Sync for Buffer<'a, T> {}
96
97pub struct MappedBuffer<'a, T: 'a> {
98    buffer: PhantomData<&'a mut Buffer<'a, T>>,
99    attachment: BufferAttachment,
100    slice: *mut T,
101    len: usize,
102}
103
104impl<'a, T: 'a> MappedBuffer<'a, T> {
105    pub fn len(&self) -> usize {
106        self.len
107    }
108}
109
110impl<'a, T: 'a> Drop for MappedBuffer<'a, T> {
111    fn drop(&mut self) {
112        if self.attachment.is_attached() {
113            // TODO: support for attaching one buffer to multiple geoms?
114            unsafe {
115                rtcUpdateGeometryBuffer(
116                    self.attachment.geom,
117                    self.attachment.buf_type,
118                    self.attachment.slot
119                );
120            }
121        }
122    }
123}
124
125impl<'a, T: 'a> Index<usize> for MappedBuffer<'a, T> {
126    type Output = T;
127
128    fn index(&self, index: usize) -> &T {
129        // TODO: We should only check in debug build
130        if index >= self.len {
131            panic!("MappedBuffer index out of bounds");
132        }
133        unsafe { &*self.slice.offset(index as isize) }
134    }
135}
136
137impl<'a, T: 'a> IndexMut<usize> for MappedBuffer<'a, T> {
138    fn index_mut(&mut self, index: usize) -> &mut T {
139        if index >= self.len {
140            panic!("MappedBuffer index out of bounds");
141        }
142        unsafe { &mut *self.slice.offset(index as isize) }
143    }
144}