fyrox_graphics/
buffer.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Buffer is a type-agnostic data storage located directly in GPU memory. It could be considered
22//! as a data block which content is a pile of bytes, whose meaning is defined externally.
23
24use crate::define_shared_wrapper;
25use crate::error::FrameworkError;
26use bytemuck::Pod;
27use fyrox_core::{array_as_u8_slice, array_as_u8_slice_mut, Downcast};
28
29/// GPU buffer kind.
30#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
31pub enum BufferKind {
32    /// Vertex buffer. It is used to supply vertex data (such as positions, normals, texture
33    /// coordinates, etc.) to GPU.
34    Vertex,
35    /// Index buffer. It is used to describe how vertices forms specific types of primitives.
36    /// For example a quad could be described by a set of 4 vertices, but 2 triangles which in their
37    /// turn consists of 6 indices (0,1,2,0,2,3 vertex indices).
38    Index,
39    /// Uniform buffer. It is used to supply context-specific data that is needed for rendering.
40    /// Usually it contains data that changes from frame-to-frame (world transform, color, etc.).
41    Uniform,
42    /// Pixel read buffer. It is a special buffer that is used to asynchronously read-back data
43    /// from GPU.
44    PixelRead,
45    /// Pixel write buffer. It is a special buffer that is used to write some data to GPU
46    /// asynchronously.
47    PixelWrite,
48}
49
50/// A hint for video driver that allows it to optimize buffer's content for more efficient use.
51#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
52pub enum BufferUsage {
53    /// The buffer contents will be modified once and used at most a few times.
54    /// The buffer contents are modified by the application, and used as the source for
55    /// drawing and image specification commands.
56    StreamDraw,
57    /// The buffer contents will be modified once and used at most a few times.
58    /// The buffer contents are modified by reading data from the GPU, and used to return that
59    /// data when queried by the application.
60    StreamRead,
61    /// The buffer contents will be modified once and used at most a few times.
62    /// The buffer contents are modified by the application, and used as the source for
63    /// drawing and image specification commands.
64    StreamCopy,
65    /// The buffer contents will be modified once and used many times.
66    /// The buffer contents are modified by the application, and used as the source for
67    /// drawing and image specification commands.
68    StaticDraw,
69    /// The buffer contents will be modified once and used many times.
70    /// The buffer contents are modified by reading data from the GPU, and used to return that
71    /// data when queried by the application.
72    StaticRead,
73    /// The buffer contents will be modified once and used many times.
74    /// The buffer contents are modified by reading data from the GPU, and used as the source for
75    ///  drawing and image specification commands.
76    StaticCopy,
77    /// The buffer contents will be modified repeatedly and used many times.
78    /// The buffer contents are modified by the application, and used as the source for
79    /// drawing and image specification commands.
80    DynamicDraw,
81    /// The buffer contents will be modified repeatedly and used many times.
82    /// The buffer contents are modified by reading data from the GPU, and used to return that
83    /// data when queried by the application.
84    DynamicRead,
85    /// The buffer contents will be modified repeatedly and used many times.
86    /// The buffer contents are modified by reading data from the GPU, and used as the source for
87    /// drawing and image specification commands.
88    DynamicCopy,
89}
90
91/// Buffer is a type-agnostic data storage located directly in GPU memory. It could be considered
92/// as a data block which content is a pile of bytes, whose meaning is defined externally.
93///
94/// ## Example
95///
96/// The following example shows how to create a uniform buffer, that could be used for rendering
97/// a static object.
98///
99/// ```rust
100/// use fyrox_graphics::{
101///     buffer::{GpuBuffer, BufferKind, BufferUsage},
102///     core::{algebra::Vector3, color::Color},
103///     error::FrameworkError,
104///     server::GraphicsServer,
105///     uniform::DynamicUniformBuffer,
106/// };
107///
108/// fn create_buffer(server: &dyn GraphicsServer) -> Result<GpuBuffer, FrameworkError> {
109///     let uniforms = DynamicUniformBuffer::new()
110///         .with(&Vector3::new(1.0, 2.0, 3.0))
111///         .with(&Color::WHITE)
112///         .with(&123.0f32)
113///         .finish();
114///
115///     let buffer =
116///         server.create_buffer(uniforms.len(), BufferKind::Uniform, BufferUsage::StaticDraw)?;
117///
118///     buffer.write_data(&uniforms)?;
119///
120///     Ok(buffer)
121/// }
122/// ```
123pub trait GpuBufferTrait: Downcast {
124    /// Returns usage kind of the buffer.
125    fn usage(&self) -> BufferUsage;
126    /// Returns buffer kind.
127    fn kind(&self) -> BufferKind;
128    /// Returns total size of the buffer in bytes.
129    fn size(&self) -> usize;
130    /// Writes an arbitrary number of bytes from the given slice.
131    fn write_data(&self, data: &[u8]) -> Result<(), FrameworkError>;
132    /// Read an arbitrary number of bytes from the buffer (GPU memory) to the given slice. The
133    /// amount of the data that will be attempted to read is defined by the length of the given
134    /// slice.
135    fn read_data(&self, data: &mut [u8]) -> Result<(), FrameworkError>;
136}
137
138impl dyn GpuBufferTrait {
139    /// Tries to write typed data to the buffer. The data type must implement [`Pod`] trait for
140    /// safe usage.
141    pub fn write_data_of_type<T: Pod>(&self, data: &[T]) -> Result<(), FrameworkError> {
142        let data = array_as_u8_slice(data);
143        GpuBufferTrait::write_data(self, data)
144    }
145
146    /// Tries to read data from the buffer and convert them to the given type. The data type must
147    /// implement [`Pod`] trait for safe usage. The amount of the data that will be attempted to
148    /// read is defined by the length of the given slice.
149    pub fn read_data_of_type<T: Pod>(&self, data: &mut [T]) -> Result<(), FrameworkError> {
150        let data = array_as_u8_slice_mut(data);
151        GpuBufferTrait::read_data(self, data)
152    }
153}
154
155define_shared_wrapper!(GpuBuffer<dyn GpuBufferTrait>);