fyrox_graphics/
server.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//! Graphics server is an abstraction layer over various graphics APIs used on different platforms
24//! supported by the engine.
25
26use crate::{
27    buffer::{Buffer, BufferKind, BufferUsage},
28    core::Downcast,
29    error::FrameworkError,
30    framebuffer::{Attachment, FrameBuffer},
31    geometry_buffer::{GeometryBuffer, GeometryBufferDescriptor},
32    gpu_program::{GpuProgram, ShaderResourceDefinition},
33    gpu_texture::{
34        GpuTexture, GpuTextureDescriptor, GpuTextureKind, MagnificationFilter, MinificationFilter,
35        PixelKind, WrapMode,
36    },
37    query::Query,
38    read_buffer::AsyncReadBuffer,
39    stats::PipelineStatistics,
40    PolygonFace, PolygonFillMode,
41};
42use std::{
43    cell::RefCell,
44    rc::{Rc, Weak},
45};
46
47/// Graphics server capabilities.
48#[derive(Debug)]
49pub struct ServerCapabilities {
50    /// The maximum size in basic machine units of a uniform block, which must be at least 16384.
51    pub max_uniform_block_size: usize,
52    /// The minimum required alignment for uniform buffer sizes and offset. The initial value is 1.
53    pub uniform_buffer_offset_alignment: usize,
54    /// The maximum, absolute value of the texture level-of-detail bias. The value must be at least
55    /// 2.0.
56    pub max_lod_bias: f32,
57}
58
59/// A shared reference to a graphics server.
60pub type SharedGraphicsServer = Rc<dyn GraphicsServer>;
61
62/// Graphics server is an abstraction layer over various graphics APIs used on different platforms
63/// supported by the engine. Such abstraction layer tries to provide more or less high-level and
64/// unified interface, that can be used to build graphics pipelines quickly and more or less efficiently.
65///
66/// Low-level GAPI-specific optimizations could be performed using direct access to the underlying API,
67/// by downcasting to a specific type.
68pub trait GraphicsServer: Downcast {
69    /// Creates a GPU buffer with the given size and kind. Usage is a hint to the video driver
70    /// that allows to perform some potential performance optimizations.
71    fn create_buffer(
72        &self,
73        size: usize,
74        buffer_kind: BufferKind,
75        buffer_usage: BufferUsage,
76    ) -> Result<Box<dyn Buffer>, FrameworkError>;
77
78    /// Creates a new GPU texture using the given descriptor.
79    fn create_texture(
80        &self,
81        desc: GpuTextureDescriptor,
82    ) -> Result<Rc<RefCell<dyn GpuTexture>>, FrameworkError>;
83
84    /// Creates a new frame buffer using the given depth and color attachments. Depth attachment
85    /// not exist, but there must be at least one color attachment of a format that supports rendering.
86    fn create_frame_buffer(
87        &self,
88        depth_attachment: Option<Attachment>,
89        color_attachments: Vec<Attachment>,
90    ) -> Result<Box<dyn FrameBuffer>, FrameworkError>;
91
92    /// Creates a frame buffer that "connected" to the final image that will be displayed to the
93    /// screen.
94    fn back_buffer(&self) -> Box<dyn FrameBuffer>;
95
96    /// Creates a new GPU query, that can perform asynchronous data fetching from GPU. Usually it
97    /// is used to create occlusion queries.
98    fn create_query(&self) -> Result<Box<dyn Query>, FrameworkError>;
99
100    /// Creates a new named GPU program using a pair of vertex and fragment shaders. The name could
101    /// be used for debugging purposes.
102    fn create_program(
103        &self,
104        name: &str,
105        vertex_source: &str,
106        fragment_source: &str,
107    ) -> Result<Box<dyn GpuProgram>, FrameworkError>;
108
109    /// Almost the same as [`Self::create_program`], but accepts additional array of resource
110    /// definitions. The implementation of graphics server will generate proper resource bindings
111    /// in the shader code for you.
112    fn create_program_with_properties(
113        &self,
114        name: &str,
115        vertex_source: &str,
116        fragment_source: &str,
117        properties: &[ShaderResourceDefinition],
118    ) -> Result<Box<dyn GpuProgram>, FrameworkError>;
119
120    /// Creates a new read-back buffer, that can be used to obtain texture data from GPU. It can be
121    /// used to read rendering result from GPU to CPU memory and save the result to disk.
122    fn create_async_read_buffer(
123        &self,
124        pixel_size: usize,
125        pixel_count: usize,
126    ) -> Result<Box<dyn AsyncReadBuffer>, FrameworkError>;
127
128    /// Creates a new geometry buffer, which consists of one or more vertex buffers and only one
129    /// element buffer. Geometry buffer could be considered as a complex mesh storage allocated on
130    /// GPU.
131    fn create_geometry_buffer(
132        &self,
133        desc: GeometryBufferDescriptor,
134    ) -> Result<Box<dyn GeometryBuffer>, FrameworkError>;
135
136    /// Creates a weak reference to the shared graphics server.
137    fn weak(self: Rc<Self>) -> Weak<dyn GraphicsServer>;
138
139    /// Sends all scheduled GPU command buffers for execution on GPU without waiting for a certain
140    /// threshold.
141    fn flush(&self);
142
143    /// Waits until all the scheduled GPU commands are fully executed. This is blocking operation, and
144    /// it blocks the current thread until all the commands are fully executed.
145    fn finish(&self);
146
147    /// Unbinds the all bound resources from the graphics pipeline.
148    fn invalidate_resource_bindings_cache(&self);
149
150    /// Returns GPU pipeline statistics. See [`PipelineStatistics`] for more info.
151    fn pipeline_statistics(&self) -> PipelineStatistics;
152
153    /// Swaps the front and back buffers and thus presenting the final image on screen. There could
154    /// be more than two buffers, and it is up to the graphics server implementation to choose the
155    /// right amount, but it can't be less than two.
156    fn swap_buffers(&self) -> Result<(), FrameworkError>;
157
158    /// Notifies the graphics server that the size of the back buffer has changed. It has very limited
159    /// use and there are very few platforms (Linux with Wayland mostly) that needs this function to
160    /// be called.
161    fn set_frame_size(&self, new_size: (u32, u32));
162
163    /// Returns current capabilities of the graphics server. See [`ServerCapabilities`] for more info.
164    fn capabilities(&self) -> ServerCapabilities;
165
166    /// Sets current polygon fill mode. See [`PolygonFace`] and [`PolygonFillMode`] docs for more info.
167    fn set_polygon_fill_mode(&self, polygon_face: PolygonFace, polygon_fill_mode: PolygonFillMode);
168
169    /// A shortcut for [`Self::create_texture`], that creates a rectangular texture with the given
170    /// size and pixel kind.
171    fn create_2d_render_target(
172        &self,
173        pixel_kind: PixelKind,
174        width: usize,
175        height: usize,
176    ) -> Result<Rc<RefCell<dyn GpuTexture>>, FrameworkError> {
177        self.create_texture(GpuTextureDescriptor {
178            kind: GpuTextureKind::Rectangle { width, height },
179            pixel_kind,
180            min_filter: MinificationFilter::Nearest,
181            mag_filter: MagnificationFilter::Nearest,
182            s_wrap_mode: WrapMode::ClampToEdge,
183            t_wrap_mode: WrapMode::ClampToEdge,
184            r_wrap_mode: WrapMode::ClampToEdge,
185            ..Default::default()
186        })
187    }
188}