fyrox_graphics/framebuffer.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#![warn(missing_docs)]
22
23//! Frame buffer is a set of images that is used as a storage for an image generated by a renderer.
24//! It consists of one or more color buffers and an optional depth/stencil buffer. See [`FrameBuffer`]
25//! docs for more info.
26
27use crate::{
28 buffer::Buffer,
29 core::{color::Color, math::Rect, Downcast},
30 error::FrameworkError,
31 geometry_buffer::GeometryBuffer,
32 gpu_program::{GpuProgram, UniformLocation},
33 gpu_texture::{CubeMapFace, GpuTexture},
34 DrawParameters, ElementRange,
35};
36use std::{cell::RefCell, rc::Rc};
37
38/// Frame buffer attachment kind.
39#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug, Eq)]
40pub enum AttachmentKind {
41 /// Color attachment, it should have a format that supports rendering (for example it cannot be
42 /// a compressed texture format).
43 Color,
44 /// Combined depth + stencil (usually it is 24 bits for depth and 8 for stencil) attachment.
45 DepthStencil,
46 /// Depth-only attachment. Usually it is 16 or 32 bits texture.
47 Depth,
48}
49
50/// Frame buffer attachment.
51pub struct Attachment {
52 /// Current kind of attachment. Tells the renderer how the texture should be used.
53 pub kind: AttachmentKind,
54 /// A texture that is used to write the rendered image to.
55 pub texture: Rc<RefCell<dyn GpuTexture>>,
56}
57
58/// Defines a range of data in a particular buffer.
59#[derive(Default)]
60pub enum BufferDataUsage {
61 /// Use everything at once.
62 #[default]
63 UseEverything,
64 /// Use just a segment of data starting from the given `offset` with `size` bytes. It is used
65 /// in cases where you have a large buffer with lots of small blocks of information about
66 /// different objects. Instead of having a number of small buffers (which is memory- and performance
67 /// inefficient), you put everything into a large buffer and fill it lots of info at once and then
68 /// binding segments of the data the to the pipeline.
69 UseSegment {
70 /// Offset from the beginning of the buffer in bytes.
71 offset: usize,
72 /// Size of the data block in bytes.
73 size: usize,
74 },
75}
76
77/// Defines a way how a texture will be bound to a pipeline.
78pub enum TextureShaderLocation {
79 /// Obsolete texture binding mode where the video driver decides binding point (index) for a specific
80 /// uniform location automatically. It is not advised to use this mode, and you should always
81 /// prefer using [`TextureShaderLocation::ExplicitBinding`] instead.
82 Uniform(UniformLocation),
83 /// Defines a texture binding point explicitly using a number.
84 ExplicitBinding(usize),
85}
86
87/// Data buffer binding location.
88// TODO: Remove when raw shaders will be replaced with Fyrox-native ones. This struct should turn
89// into a simple index.
90pub enum BufferLocation {
91 /// Obsolete automatic binding mode. It is a sort of implicit binding mode where the video driver
92 /// automatically assigns binding points for shader resources, and then you need to fetch these
93 /// values by name of a uniform variable and provide them in as `shader_location`. It is strongly
94 /// advised to use [`BufferLocation::Explicit`] mode instead. This mode is left mostly for
95 /// compatibility with the old code.
96 Auto {
97 /// An automatically generated index fetched from the video driver using
98 /// [`GpuProgram::uniform_block_index`].
99 shader_location: usize,
100 },
101 /// Explicit binding mode where you strictly define expected binding point for the buffer.
102 Explicit {
103 /// Binding point index.
104 binding: usize,
105 },
106}
107
108/// A resource binding defines where to bind specific GPU resources.
109pub enum ResourceBinding<'a> {
110 /// Texture binding.
111 Texture {
112 /// A shared reference to a texture.
113 texture: Rc<RefCell<dyn GpuTexture>>,
114 /// Binding mode for the texture.
115 shader_location: TextureShaderLocation,
116 },
117 /// Generic data buffer binding.
118 Buffer {
119 /// A reference to a buffer.
120 buffer: &'a dyn Buffer,
121 /// Binding mode for the buffer.
122 binding: BufferLocation,
123 /// Data portion to use.
124 data_usage: BufferDataUsage,
125 },
126}
127
128impl ResourceBinding<'_> {
129 /// Creates a new texture binding using uniform location. See [`TextureShaderLocation::Uniform`]
130 /// docs for more info.
131 pub fn texture(
132 texture: &Rc<RefCell<dyn GpuTexture>>,
133 shader_location: &UniformLocation,
134 ) -> Self {
135 Self::Texture {
136 texture: texture.clone(),
137 shader_location: TextureShaderLocation::Uniform(shader_location.clone()),
138 }
139 }
140
141 /// Creates a new explicit texture binding. See [`TextureShaderLocation::ExplicitBinding`] for
142 /// more info.
143 pub fn texture_with_binding(texture: &Rc<RefCell<dyn GpuTexture>>, binding: usize) -> Self {
144 Self::Texture {
145 texture: texture.clone(),
146 shader_location: TextureShaderLocation::ExplicitBinding(binding),
147 }
148 }
149}
150
151/// Resource binding group defines a set of bindings.
152pub struct ResourceBindGroup<'a> {
153 /// A reference to resource bindings array.
154 pub bindings: &'a [ResourceBinding<'a>],
155}
156
157/// Statistics for a single GPU draw call.
158#[derive(Debug, Copy, Clone, Default)]
159pub struct DrawCallStatistics {
160 /// Total number of rendered triangles.
161 pub triangles: usize,
162}
163
164/// Frame buffer is a set of images that is used as a storage for an image generated by a renderer.
165/// It consists of one or more color buffers and an optional depth/stencil buffer. Frame buffer is
166/// a high level abstraction that consolidates multiple images and supports drawing meshes to them
167/// with various drawing options.
168pub trait FrameBuffer: Downcast {
169 /// Returns a list of color attachments.
170 fn color_attachments(&self) -> &[Attachment];
171
172 /// Returns an optional depth/stencil attachment.
173 fn depth_attachment(&self) -> Option<&Attachment>;
174
175 /// Sets an active face of a cube map (only for frame buffers that using cube maps for rendering).
176 fn set_cubemap_face(&mut self, attachment_index: usize, face: CubeMapFace);
177
178 /// Performs data transfer from one frame buffer to another with scaling. It copies a region
179 /// defined by `src_x0`, `src_y0`, `src_x1`, `src_y1` coordinates from the frame buffer and
180 /// "pastes" it to the other frame buffer into a region defined by `dst_x0`, `dst_y0`, `dst_x1`,
181 /// `dst_y1` coordinates. If the source rectangle does not match the destination, the image will
182 /// be interpolated using nearest interpolation.
183 ///
184 /// This method can copy only specific parts of the image: `copy_color` tells the method to copy
185 /// the data from
186 fn blit_to(
187 &self,
188 dest: &dyn FrameBuffer,
189 src_x0: i32,
190 src_y0: i32,
191 src_x1: i32,
192 src_y1: i32,
193 dst_x0: i32,
194 dst_y0: i32,
195 dst_x1: i32,
196 dst_y1: i32,
197 copy_color: bool,
198 copy_depth: bool,
199 copy_stencil: bool,
200 );
201
202 /// Clears the frame buffer in the given viewport with the given set of optional values. This
203 /// method clears multiple attachments at once. What will be cleared defined by the provided
204 /// values. If `color` is not [`None`], then all the color attachments will be cleared with the
205 /// given color. The same applies to depth and stencil buffers.
206 fn clear(
207 &mut self,
208 viewport: Rect<i32>,
209 color: Option<Color>,
210 depth: Option<f32>,
211 stencil: Option<i32>,
212 );
213
214 /// Draws the specified geometry buffer using the given GPU program and a set of resources. This
215 /// method the main method to draw anything.
216 ///
217 /// `geometry` - defines a [`GeometryBuffer`], that contains vertices and index buffers and
218 /// essentially defines a mesh to render.
219 /// `viewport` - defines an area on screen that will be used to draw.
220 /// `program` - a [`GpuProgram`] defines a set of shaders (usually a pair of vertex + fragment)
221 /// that will define how the mesh will be rendered.
222 /// `params` - [`DrawParameters`] defines the state of graphics pipeline and essentially sets
223 /// a bunch of various parameters (such as backface culling, blending mode, various tests, etc.)
224 /// that will define how the rendering process is performed.
225 /// `resources` - a set of resource bind groups, that in their turn provides a set of resources
226 /// that bound to specific binding points.
227 /// `element_range` - defines which range of elements to draw.
228 fn draw(
229 &mut self,
230 geometry: &dyn GeometryBuffer,
231 viewport: Rect<i32>,
232 program: &dyn GpuProgram,
233 params: &DrawParameters,
234 resources: &[ResourceBindGroup],
235 element_range: ElementRange,
236 ) -> Result<DrawCallStatistics, FrameworkError>;
237
238 /// Almost the same as [`Self::draw`], but draws multiple instances at once. The caller must
239 /// supply all the required data per each instance, it could be done in different ways. The data
240 /// could be supplied in vertex attributes, uniform buffers, textures, etc.
241 fn draw_instances(
242 &mut self,
243 count: usize,
244 geometry: &dyn GeometryBuffer,
245 viewport: Rect<i32>,
246 program: &dyn GpuProgram,
247 params: &DrawParameters,
248 resources: &[ResourceBindGroup],
249 ) -> DrawCallStatistics;
250}