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}