1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Graphics rendering traits, implemented by backends.
use super::*;
/// Graphics rendering backend.
/// This trait is implemented by compatible backends, eg. OpenGL, Vulkan etc.
pub trait RenderBackend: EventHandlerBackend {
/// Information returned by the backend.
type Info: std::fmt::Debug;
/// The frame builder, created and dropped every frame.
type Frame<'a>: RenderFrame<'a, Error = Self::Error>
where
Self: 'a;
/// Error returned by trait methods.
type Error: std::error::Error + 'static;
/// Return information about the backend.
fn info(&self) -> Self::Info;
/// Create a [`Self::Frame`] object.
fn frame(&mut self) -> Self::Frame<'_>;
/// Create a new shader program.
fn shader(
&mut self,
shader: ShaderSource,
meta: ShaderDescriptor,
) -> Result<ShaderId, ShaderError>;
/// Create a new texture. Can be used for render targets as well.
fn texture<T: AsBytes>(&mut self, texture: Texture<T>) -> Result<TextureId, Self::Error>;
/// Set the texture filter mode.
fn texture_set_filter(&mut self, texture: TextureId, filter: FilterMode) {
self.texture_set_min_filter(texture, filter);
self.texture_set_mag_filter(texture, filter);
}
/// Set the texture *min* filter mode.
fn texture_set_min_filter(&mut self, texture: TextureId, filter: FilterMode);
/// Set the texture *mag* filter mode.
fn texture_set_mag_filter(&mut self, texture: TextureId, filter: FilterMode);
/// Set the texture wrap mode.
fn texture_set_wrap(&mut self, texture: TextureId, wrap: TextureWrap);
/// Resize texture.
fn texture_resize(
&mut self,
texture: TextureId,
size: Size<u32>,
bytes: &[color::Rgba8],
) -> Result<(), Self::Error>;
/// Update texture area.
fn texture_update(
&mut self,
texture: TextureId,
area: Rect<u32>,
pixels: &[color::Rgba8],
) -> Result<(), Self::Error>;
/// Delete texture.
fn texture_delete(&mut self, texture: TextureId);
/// Create a buffer resource object.
fn buffer<T>(
&mut self,
kind: BufferKind,
usage: BufferUsage,
data: BufferSource<T>,
) -> Result<BufferId, Self::Error>;
/// Update a buffer object.
fn buffer_update<T>(
&mut self,
buffer: BufferId,
kind: BufferKind,
data: &[T],
) -> Result<(), Self::Error>;
/// Delete buffer object.
fn buffer_delete(&mut self, buffer: BufferId, kind: BufferKind);
/// Create a new render pass.
fn pass(&mut self, desc: PassDescriptor) -> Result<PassId, Self::Error>;
/// Read pass color attachment into slice.
fn pass_read_color_attachment(
&self,
pass: PassId,
output: &mut [color::Rgba8],
) -> Result<(), Self::Error>;
/// Read pass depth attachment into slice.
fn pass_read_depth_attachment(
&self,
pass: PassId,
output: &mut [f32],
) -> Result<(), Self::Error>;
/// Delete a pass.
fn pass_delete(&mut self, pass: PassId);
/// Create a new render pipeline using the given shader.
fn pipeline(&mut self, shader: ShaderId, desc: PipelineDescriptor) -> PipelineId;
}
/// Methods relating to event handling.
pub trait EventHandlerBackend {
/// Handle a window resized event.
/// This can be used to resize textures, for example.
fn window_resized(&mut self, size: platform::LogicalSize);
}
/// A render frame. Created by calling [`RenderBackend::frame`] and finalized with
/// [`RenderFrame::commit`].
pub trait RenderFrame<'a> {
/// Error returned by trait methods.
type Error: std::error::Error + 'static;
/// Apply a render pipeline.
fn apply_pipeline(&mut self, pipeline: &PipelineId) -> Result<(), Self::Error>;
/// Set a new viewport rectangle.
/// Should be applied after [`RenderFrame::begin_pass`].
fn apply_viewport(&mut self, rect: Rect<i32>) -> Result<(), Self::Error>;
/// Set a new scissor rectangle.
/// Should be applied after [`RenderFrame::begin_pass`].
fn apply_scissor(&mut self, rect: Rect<i32>) -> Result<(), Self::Error>;
/// Apply shader bindings.
fn apply_bindings(&mut self, bindings: &Bindings) -> Result<(), Self::Error>;
/// Apply shader uniforms.
fn apply_uniforms<T: AsBytes>(&mut self, uniforms: &T) -> Result<(), Self::Error>;
/// Clear the view.
fn clear(&mut self, color: Option<Rgba<f32>>, depth: Option<f32>, stencil: Option<i32>);
/// Begin the final presentation pass. Drawing while this pass is active draws to the screen.
fn begin_default_pass(&mut self, action: PassAction);
/// Begin an off-screen pass.
fn begin_pass(&mut self, pass: PassId, action: PassAction);
/// End the current pass.
fn end_pass(&mut self);
/// Draw elements using the currently applied bindings and pipeline.
/// * `offset` specifies the starting offset in the index buffer.
/// * `elements` specifies how many elements to draw from the index buffer.
/// * `instances` specifies how many instances should be rendered.
fn draw(&self, offset: usize, elements: usize, instances: usize) -> Result<(), Self::Error>;
/// Finalize the frame, presenting it to the screen.
fn commit(self);
}