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::error::FrameworkError;
25use bytemuck::Pod;
26use fyrox_core::{array_as_u8_slice, array_as_u8_slice_mut, Downcast};
27
28/// GPU buffer kind.
29#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
30pub enum BufferKind {
31 /// Vertex buffer. It is used to supply vertex data (such as positions, normals, texture
32 /// coordinates, etc.) to GPU.
33 Vertex,
34 /// Index buffer. It is used to describe how vertices forms specific types of primitives.
35 /// For example a quad could be described by a set of 4 vertices, but 2 triangles which in their
36 /// turn consists of 6 indices (0,1,2,0,2,3 vertex indices).
37 Index,
38 /// Uniform buffer. It is used to supply context-specific data that is needed for rendering.
39 /// Usually it contains data that changes from frame-to-frame (world transform, color, etc.).
40 Uniform,
41 /// Pixel read buffer. It is a special buffer that is used to asynchronously read-back data
42 /// from GPU.
43 PixelRead,
44 /// Pixel write buffer. It is a special buffer that is used to write some data to GPU
45 /// asynchronously.
46 PixelWrite,
47}
48
49/// A hint for video driver that allows it to optimize buffer's content for more efficient use.
50#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
51pub enum BufferUsage {
52 /// The buffer contents will be modified once and used at most a few times.
53 /// The buffer contents are modified by the application, and used as the source for
54 /// drawing and image specification commands.
55 StreamDraw,
56 /// The buffer contents will be modified once and used at most a few times.
57 /// The buffer contents are modified by reading data from the GPU, and used to return that
58 /// data when queried by the application.
59 StreamRead,
60 /// The buffer contents will be modified once and used at most a few times.
61 /// The buffer contents are modified by the application, and used as the source for
62 /// drawing and image specification commands.
63 StreamCopy,
64 /// The buffer contents will be modified once and used many times.
65 /// The buffer contents are modified by the application, and used as the source for
66 /// drawing and image specification commands.
67 StaticDraw,
68 /// The buffer contents will be modified once and used many times.
69 /// The buffer contents are modified by reading data from the GPU, and used to return that
70 /// data when queried by the application.
71 StaticRead,
72 /// The buffer contents will be modified once and used many times.
73 /// The buffer contents are modified by reading data from the GPU, and used as the source for
74 /// drawing and image specification commands.
75 StaticCopy,
76 /// The buffer contents will be modified repeatedly and used many times.
77 /// The buffer contents are modified by the application, and used as the source for
78 /// drawing and image specification commands.
79 DynamicDraw,
80 /// The buffer contents will be modified repeatedly and used many times.
81 /// The buffer contents are modified by reading data from the GPU, and used to return that
82 /// data when queried by the application.
83 DynamicRead,
84 /// The buffer contents will be modified repeatedly and used many times.
85 /// The buffer contents are modified by reading data from the GPU, and used as the source for
86 /// drawing and image specification commands.
87 DynamicCopy,
88}
89
90/// Buffer is a type-agnostic data storage located directly in GPU memory. It could be considered
91/// as a data block which content is a pile of bytes, whose meaning is defined externally.
92///
93/// ## Example
94///
95/// The following example shows how to create a uniform buffer, that could be used for rendering
96/// a static object.
97///
98/// ```rust
99/// use fyrox_graphics::{
100/// buffer::{Buffer, BufferKind, BufferUsage},
101/// core::{algebra::Vector3, color::Color},
102/// error::FrameworkError,
103/// server::GraphicsServer,
104/// uniform::DynamicUniformBuffer,
105/// };
106///
107/// fn create_buffer(server: &dyn GraphicsServer) -> Result<Box<dyn Buffer>, FrameworkError> {
108/// let uniforms = DynamicUniformBuffer::new()
109/// .with(&Vector3::new(1.0, 2.0, 3.0))
110/// .with(&Color::WHITE)
111/// .with(&123.0f32)
112/// .finish();
113///
114/// let buffer =
115/// server.create_buffer(uniforms.len(), BufferKind::Uniform, BufferUsage::StaticDraw)?;
116///
117/// buffer.write_data(&uniforms)?;
118///
119/// Ok(buffer)
120/// }
121/// ```
122pub trait Buffer: Downcast {
123 /// Returns usage kind of the buffer.
124 fn usage(&self) -> BufferUsage;
125 /// Returns buffer kind.
126 fn kind(&self) -> BufferKind;
127 /// Returns total size of the buffer in bytes.
128 fn size(&self) -> usize;
129 /// Writes an arbitrary number of bytes from the given slice.
130 fn write_data(&self, data: &[u8]) -> Result<(), FrameworkError>;
131 /// Read an arbitrary number of bytes from the buffer (GPU memory) to the given slice. The
132 /// amount of the data that will be attempted to read is defined by the length of the given
133 /// slice.
134 fn read_data(&self, data: &mut [u8]) -> Result<(), FrameworkError>;
135}
136
137impl dyn Buffer {
138 /// Tries to write typed data to the buffer. The data type must implement [`Pod`] trait for
139 /// safe usage.
140 pub fn write_data_of_type<T: Pod>(&self, data: &[T]) -> Result<(), FrameworkError> {
141 let data = array_as_u8_slice(data);
142 Buffer::write_data(self, data)
143 }
144
145 /// Tries to read data from the buffer and convert them to the given type. The data type must
146 /// implement [`Pod`] trait for safe usage. The amount of the data that will be attempted to
147 /// read is defined by the length of the given slice.
148 pub fn read_data_of_type<T: Pod>(&self, data: &mut [T]) -> Result<(), FrameworkError> {
149 let data = array_as_u8_slice_mut(data);
150 Buffer::read_data(self, data)
151 }
152}