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