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
use crate::{math::*, *};

/// A [`Renderer`] compatible WGPU device.
///
/// A default implementation exists for `riddle_platform_winit::Window`
/// in [`WindowWGPUDevice`].
///
/// The application may implement this trait to layer the renderer on
/// top of custom WGPU renderer.
///
/// # Example
///
/// ```no_run
/// use std::sync::Arc;
/// use riddle::{common::Color, platform::*, renderer::*, *};
///
/// #[derive(Clone)]
/// struct ACustomRendererHandle {
///     // [..]
/// }
///
/// impl ACustomRendererHandle {
///     // [..]
/// #   fn new() -> Self { todo!() }
/// #   fn start_render(&self) { todo!() }
/// #   fn end_render(&self) { todo!() }
/// #   fn render_3d_scene(&self) { todo!() }
/// }
///
/// impl WGPUDevice for ACustomRendererHandle {
///     // [..]
/// #   fn begin_frame(&self) -> Result<(), WGPURendererError> { todo!() }
/// #   fn end_frame(&self) { todo!() }
/// #   fn viewport_dimensions(&self) -> math::Vector2<f32>  { todo!() }
/// #   fn with_device_info<R, F: FnOnce(&WGPUDeviceInfo) -> Result<R, WGPURendererError>>(&self, f: F) -> Result<R, WGPURendererError> { todo!() }
/// #   fn with_frame<R, F: FnOnce(&wgpu::SwapChainFrame) -> Result<R, WGPURendererError>>(&self, f: F) -> Result<R, WGPURendererError> { todo!() }
/// }
///
/// fn main() -> Result<(), RiddleError> {
///     let rdl =  RiddleLib::new()?;
///     let window = WindowBuilder::new().build(rdl.context())?;
///
///     let custom_renderer = ACustomRendererHandle::new();
///
///     let renderer = Renderer::new_from_device(custom_renderer.clone())?;
///
///     rdl.run(move |rdl| match rdl.event() {
///         Event::Platform(PlatformEvent::WindowClose(_)) => rdl.quit(),
///         Event::ProcessFrame => {
///             custom_renderer.start_render();
///             custom_renderer.render_3d_scene();
///
///             renderer.render(|render_ctx| {
///                 render_ctx.clear(Color::RED)
///             }).unwrap();
///
///             custom_renderer.end_render();
///         }
///         _ => (),
///     })
/// }
/// ```
pub trait WGPUDevice {
	/// Called when the [`Renderer`] begins rendering to the swap chain frame.
	///
	/// Invoked through [`Renderer::render`]
	fn begin_frame(&self) -> Result<()>;

	/// When the renderer is done renderering to the swap chain frame.
	///
	/// Invoked by a [`RenderContext::present`] call on the context returned from
	/// [`Renderer::render`].
	fn end_frame(&self);

	/// The viewport dimensions of the swapchain frame.
	///
	/// This controls the projection matrix used by the sprite renderer.
	fn viewport_dimensions(&self) -> Vector2<f32>;

	/// Provides a reference to the set of wgpu device state for use by the renderer.
	fn with_device_info<R, F: FnOnce(&WGPUDeviceInfo) -> Result<R>>(&self, f: F) -> Result<R>;

	/// Provide a reference to the current swap chain frame for use by the
	/// renderer.
	fn with_frame<R, F: FnOnce(&wgpu::SwapChainFrame) -> Result<R>>(&self, f: F) -> Result<R>;
}

pub struct WGPUDeviceInfo<'a> {
	pub device: &'a wgpu::Device,
	pub queue: &'a wgpu::Queue,
}