gcrecomp_runtime/graphics/
renderer.rs1use crate::graphics::framebuffer::FrameBuffer;
3use crate::graphics::gx::GXProcessor;
4use crate::graphics::shaders::ShaderManager;
5use crate::graphics::upscaler::Upscaler;
6use anyhow::Result;
7use std::sync::Arc;
8use wgpu::*;
9
10pub struct Renderer {
11 device: Device,
12 queue: Queue,
13 surface: Surface<'static>,
14 config: SurfaceConfiguration,
15 upscaler: Upscaler,
16 frame_buffers: Vec<FrameBuffer>,
17 current_resolution: (u32, u32),
18 target_resolution: (u32, u32),
19 gx_processor: GXProcessor,
20 shader_manager: ShaderManager,
21 _window: Arc<winit::window::Window>,
22}
23
24impl Renderer {
25 pub fn new(window: Arc<winit::window::Window>) -> Result<Self> {
26 let instance = Instance::new(InstanceDescriptor::default());
27 let surface = instance.create_surface(window.clone())?;
29
30 let adapter = pollster::block_on(instance.request_adapter(&RequestAdapterOptions {
31 power_preference: PowerPreference::HighPerformance,
32 compatible_surface: Some(&surface),
33 force_fallback_adapter: false,
34 }))
35 .ok_or_else(|| anyhow::anyhow!("Failed to find suitable GPU adapter"))?;
36
37 let (device, queue) = pollster::block_on(adapter.request_device(
38 &DeviceDescriptor {
39 label: None,
40 required_features: Features::empty(),
41 required_limits: Limits::default(),
42 },
43 None,
44 ))?;
45
46 let size = window.inner_size();
47 let config = surface
48 .get_default_config(&adapter, size.width, size.height)
49 .ok_or_else(|| anyhow::anyhow!("Failed to get surface config"))?;
50
51 surface.configure(&device, &config);
52
53 let upscaler = Upscaler::new(&device, &config)?;
54 let gx_processor = GXProcessor::new();
55 let mut shader_manager = ShaderManager::new();
56
57 let default_vert = r#"
59 struct VertexInput {
60 @location(0) position: vec3<f32>,
61 @location(1) tex_coord: vec2<f32>,
62 }
63 struct VertexOutput {
64 @builtin(position) position: vec4<f32>,
65 @location(0) tex_coord: vec2<f32>,
66 }
67 @vertex
68 fn main(input: VertexInput) -> VertexOutput {
69 var output: VertexOutput;
70 output.position = vec4<f32>(input.position, 1.0);
71 output.tex_coord = input.tex_coord;
72 return output;
73 }
74 "#;
75
76 let default_frag = r#"
77 @group(0) @binding(0) var texture: texture_2d<f32>;
78 @group(0) @binding(1) var sampler: sampler;
79 struct FragmentInput {
80 @location(0) tex_coord: vec2<f32>,
81 }
82 @fragment
83 fn main(input: FragmentInput) -> @location(0) vec4<f32> {
84 return textureSample(texture, sampler, input.tex_coord);
85 }
86 "#;
87
88 shader_manager.load_shader(&device, "default_vertex", default_vert)?;
89 shader_manager.load_shader(&device, "default_fragment", default_frag)?;
90
91 Ok(Self {
92 device,
93 queue,
94 surface,
95 config,
96 upscaler,
97 frame_buffers: Vec::new(),
98 current_resolution: (640, 480), target_resolution: (size.width, size.height),
100 gx_processor,
101 shader_manager,
102 _window: window,
103 })
104 }
105
106 pub fn resize(&mut self, width: u32, height: u32) {
107 self.target_resolution = (width, height);
108 self.config.width = width;
109 self.config.height = height;
110 self.surface.configure(&self.device, &self.config);
111 }
112
113 pub fn set_resolution(&mut self, width: u32, height: u32) {
114 self.current_resolution = (width, height);
115 }
116
117 pub fn set_upscale_factor(&mut self, factor: f32) -> Result<()> {
118 let target_w = (self.current_resolution.0 as f32 * factor) as u32;
119 let target_h = (self.current_resolution.1 as f32 * factor) as u32;
120 self.target_resolution = (target_w, target_h);
121 Ok(())
122 }
123
124 pub fn begin_frame(&mut self) -> Result<wgpu::SurfaceTexture> {
125 let output = self.surface.get_current_texture()?;
126 Ok(output)
127 }
128
129 pub fn end_frame(&mut self, frame: wgpu::SurfaceTexture) {
130 frame.present();
131 }
132
133 pub fn device(&self) -> &Device {
134 &self.device
135 }
136
137 pub fn queue(&self) -> &Queue {
138 &self.queue
139 }
140}