Skip to content

Commit

Permalink
fix: fixed issue with lower end platforms not supporting larger textu…
Browse files Browse the repository at this point in the history
…re dimensions
  • Loading branch information
lukexor committed Jun 13, 2024
1 parent 6b3f690 commit ef214db
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 52 deletions.
12 changes: 9 additions & 3 deletions tetanes/src/nes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ impl Nes {
}
}

/// Request renderer resources (creating gui context, window, painter, etc).
///
/// # Errors
///
/// Returns an error if any resources can't be created correctly or `init_running` has already
/// been called.
pub(crate) fn request_resources(
&mut self,
event_loop: &EventLoopWindowTarget<NesEvent>,
Expand All @@ -130,15 +136,15 @@ impl Nes {
let window = Arc::clone(&window);
let event_tx = tx.clone();
async move {
debug!("creating painter...");
match Renderer::create_painter(window).await {
Ok(painter) => {
painter_tx.send(painter).expect("failed to send painter");
event_tx.nes_event(RendererEvent::ResourcesReady);
}
Err(err) => {
event_tx.nes_event(UiEvent::Error(format!(
"failed to create painter: {err:?}"
)));
error!("failed to create painter: {err:?}");
event_tx.nes_event(UiEvent::Terminate);
}
}
}
Expand Down
81 changes: 44 additions & 37 deletions tetanes/src/nes/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl Nes {
trace!("event: {event:?}");
}

match event {
match &event {
Event::Resumed => {
let state = if let State::Running(state) = &mut self.state {
if platform::supports(platform::Feature::Suspend) {
Expand All @@ -242,37 +242,49 @@ impl Nes {
state.repaint_times.insert(window_id, Instant::now());
}
}
Event::UserEvent(NesEvent::Renderer(RendererEvent::ResourcesReady)) => {
if let Err(err) = self.init_running(event_loop) {
error!("failed to create window: {err:?}");
event_loop.exit();
return;
}
Event::UserEvent(event) => match event {
NesEvent::Renderer(RendererEvent::ResourcesReady) => {
if let Err(err) = self.init_running(event_loop) {
error!("failed to create window: {err:?}");
event_loop.exit();
return;
}

// Disable device events to save some cpu as they're mostly duplicated in
// WindowEvents
event_loop.listen_device_events(DeviceEvents::Never);
// Disable device events to save some cpu as they're mostly duplicated in
// WindowEvents
event_loop.listen_device_events(DeviceEvents::Never);

if let State::Running(state) = &mut self.state {
if let Some(window) = state.renderer.root_window() {
if window.is_visible().unwrap_or(true) {
state.repaint_times.insert(window.id(), Instant::now());
} else {
// Immediately redraw the root window on start if not
// visible. Fixes a bug where `window.request_redraw()` events
// may not be sent if the window isn't visible, which is the
// case until the first frame is drawn.
if let Err(err) = state.renderer.redraw(
window.id(),
event_loop,
&mut state.gamepads,
&mut state.cfg,
) {
state.renderer.on_error(err);
if let State::Running(state) = &mut self.state {
if let Some(window) = state.renderer.root_window() {
if window.is_visible().unwrap_or(true) {
state.repaint_times.insert(window.id(), Instant::now());
} else {
// Immediately redraw the root window on start if not
// visible. Fixes a bug where `window.request_redraw()` events
// may not be sent if the window isn't visible, which is the
// case until the first frame is drawn.
if let Err(err) = state.renderer.redraw(
window.id(),
event_loop,
&mut state.gamepads,
&mut state.cfg,
) {
state.renderer.on_error(err);
}
}
}
}
}
NesEvent::Ui(UiEvent::Terminate) => event_loop.exit(),
_ => (),
},
Event::LoopExiting => {
#[cfg(feature = "profiling")]
puffin::set_scopes_on(false);

// Wasm should never be able to exit
#[cfg(target_arch = "wasm32")]
panic!("exited unexpectedly");
}
_ => (),
}
Expand Down Expand Up @@ -350,7 +362,7 @@ impl Running {
Event::WindowEvent {
window_id, event, ..
} => {
let res = self.renderer.on_window_event(window_id, &event, &self.cfg);
let res = self.renderer.on_window_event(window_id, &event);
if res.repaint && event != WindowEvent::RedrawRequested {
self.repaint_times.insert(window_id, Instant::now());
}
Expand Down Expand Up @@ -466,24 +478,19 @@ impl Running {
);
}
}
NesEvent::Ui(event) => {
if let UiEvent::Terminate = event {
event_loop.exit()
} else {
self.on_ui_event(event);
}
}
NesEvent::Ui(event) => self.on_ui_event(event),
_ => (),
}
}
Event::LoopExiting => {
#[cfg(feature = "profiling")]
puffin::set_scopes_on(false);

if let Err(err) = self.renderer.save(&self.cfg) {
error!("failed to save rendererer state: {err:?}");
}
self.renderer.destroy();

// Wasm should never be able to exit
#[cfg(target_arch = "wasm32")]
panic!("exited unexpectedly");
}
_ => (),
}
Expand Down
56 changes: 44 additions & 12 deletions tetanes/src/nes/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,22 +728,54 @@ impl Renderer {
use wgpu::Backends;
// TODO: Support webgpu when more widely supported
let supported_backends = Backends::VULKAN | Backends::METAL | Backends::DX12 | Backends::GL;
let mut painter = Painter::new(
egui_wgpu::WgpuConfiguration {
supported_backends,
present_mode: wgpu::PresentMode::AutoVsync,
desired_maximum_frame_latency: Some(2),
..Default::default()
},
1,
None,
false,
);

// The window must be ready with a non-zero size before `Painter::set_window` is called,
// otherwise the wgpu surface won't be configured correctly.
Self::wait_for_window(&window).await;
painter.set_window(ViewportId::ROOT, Some(window)).await?;

let wgpu_cfg = egui_wgpu::WgpuConfiguration {
supported_backends,
present_mode: wgpu::PresentMode::AutoVsync,
..Default::default()
};
let mut painter = Painter::new(wgpu_cfg.clone(), 1, None, false);

// Creating device may fail if adapter doesn't support our requested cfg above, so try to
// recover with lower limits. Specifically max_texture_dimension_2d has a downlevel default
// of 2048. egui_wgpu wants 8192 for 4k displays, but not all platforms support that yet.
if let Err(err) = painter
.set_window(ViewportId::ROOT, Some(Arc::clone(&window)))
.await
{
if let egui_wgpu::WgpuError::RequestDeviceError(_) = err {
painter = Painter::new(
egui_wgpu::WgpuConfiguration {
device_descriptor: Arc::new(|adapter| {
let base_limits = if adapter.get_info().backend == wgpu::Backend::Gl {
wgpu::Limits::downlevel_webgl2_defaults()
} else {
wgpu::Limits::default()
};
wgpu::DeviceDescriptor {
label: Some("egui wgpu device"),
required_features: wgpu::Features::default(),
required_limits: wgpu::Limits {
max_texture_dimension_2d: 4096,
..base_limits
},
}
}),
..wgpu_cfg
},
1,
None,
false,
);
painter.set_window(ViewportId::ROOT, Some(window)).await?;
} else {
return Err(err.into());
}
}

let adapter_info = painter.render_state().map(|state| state.adapter.get_info());
if let Some(info) = adapter_info {
Expand Down

0 comments on commit ef214db

Please sign in to comment.