refactor for resizable
This commit is contained in:
parent
29a5c272b4
commit
5f7e7db307
4 changed files with 88 additions and 57 deletions
|
@ -1,10 +1,10 @@
|
|||
use pixels::{Pixels, SurfaceTexture};
|
||||
use winit::window::Window;
|
||||
pub struct WindowData {
|
||||
pub struct Renderer {
|
||||
pub pixels: Pixels,
|
||||
}
|
||||
|
||||
impl WindowData {
|
||||
impl Renderer {
|
||||
pub fn new(factor: u32, window: &Window) -> Self {
|
||||
let pixels = {
|
||||
let window_size = window.inner_size();
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::window::ResolutionData;
|
|||
|
||||
use super::{
|
||||
utils::{find_memorytype_index, record_submit_commandbuffer},
|
||||
WindowDataManager,
|
||||
RendererBackendManager,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
|
@ -37,7 +37,7 @@ pub(super) struct VulkanData {
|
|||
}
|
||||
|
||||
impl VulkanData {
|
||||
pub(super) unsafe fn new(manager: &WindowDataManager, surface: &SurfaceData) -> Self {
|
||||
pub(super) unsafe fn new(manager: &RendererBackendManager, surface: &SurfaceData) -> Self {
|
||||
let pdevices = manager
|
||||
.instance
|
||||
.enumerate_physical_devices()
|
||||
|
@ -215,7 +215,7 @@ pub(super) struct SurfaceData {
|
|||
}
|
||||
|
||||
impl SurfaceData {
|
||||
pub(super) unsafe fn new(window: &Window, manager: &WindowDataManager) -> Self {
|
||||
pub(super) unsafe fn new(window: &Window, manager: &RendererBackendManager) -> Self {
|
||||
let surface = ash_window::create_surface(
|
||||
&manager.entry,
|
||||
&manager.instance,
|
||||
|
@ -259,7 +259,7 @@ pub(super) struct SwapchainData {
|
|||
impl SwapchainData {
|
||||
pub(super) unsafe fn new(
|
||||
resolutions: ResolutionData,
|
||||
manager: &WindowDataManager,
|
||||
manager: &RendererBackendManager,
|
||||
|
||||
surface: &SurfaceData,
|
||||
vulkan: &VulkanData,
|
||||
|
|
|
@ -26,12 +26,12 @@ mod utils;
|
|||
const SHADER: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/shaders/shader.spv"));
|
||||
const VERTICES: [Vertex; 3] = [Vertex(-1.0, -1.0), Vertex(3.0, -1.0), Vertex(-1.0, 3.0)];
|
||||
|
||||
pub struct WindowDataManager {
|
||||
pub struct RendererBackendManager {
|
||||
entry: Entry,
|
||||
instance: Instance,
|
||||
}
|
||||
|
||||
impl WindowDataManager {
|
||||
impl RendererBackendManager {
|
||||
pub fn new(display_handle: RawDisplayHandle) -> Self {
|
||||
let entry = Entry::linked();
|
||||
let name = std::ffi::CString::new("gameboy").unwrap();
|
||||
|
@ -71,28 +71,28 @@ impl WindowDataManager {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for WindowDataManager {
|
||||
impl Drop for RendererBackendManager {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.instance.destroy_instance(None) };
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowData {
|
||||
pub struct RendererBackend {
|
||||
inner: VulkanWindowInner,
|
||||
filter_chain: FilterChain,
|
||||
manager: Arc<WindowDataManager>,
|
||||
manager: Arc<RendererBackendManager>,
|
||||
}
|
||||
|
||||
pub struct WindowOptions {
|
||||
pub shader_path: PathBuf,
|
||||
}
|
||||
|
||||
impl WindowData {
|
||||
impl RendererBackend {
|
||||
pub fn new(
|
||||
resolutions: ResolutionData,
|
||||
window: &Window,
|
||||
options: WindowOptions,
|
||||
manager: Arc<WindowDataManager>,
|
||||
manager: Arc<RendererBackendManager>,
|
||||
) -> Self {
|
||||
let inner = unsafe { VulkanWindowInner::new(resolutions, window, manager.as_ref()) };
|
||||
|
||||
|
@ -129,23 +129,22 @@ impl WindowData {
|
|||
unsafe { self.inner.new_frame(buffer) };
|
||||
}
|
||||
|
||||
pub fn render(&mut self) {
|
||||
unsafe { self.inner.render(&mut self.filter_chain) };
|
||||
pub fn render(&mut self, resolutions: ResolutionData, manager: &RendererBackendManager) {
|
||||
unsafe {
|
||||
self.inner
|
||||
.render(&mut self.filter_chain, resolutions, manager)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct VulkanWindowInner {
|
||||
vulkan_data: VulkanData,
|
||||
|
||||
vertex_input_buffer: vk::Buffer,
|
||||
renderpass: vk::RenderPass,
|
||||
pipeline_layout: vk::PipelineLayout,
|
||||
|
||||
graphics_pipelines: Vec<vk::Pipeline>,
|
||||
|
||||
shader_module: vk::ShaderModule,
|
||||
vertex_input_buffer_memory: vk::DeviceMemory,
|
||||
|
||||
swapchain: SwapchainData,
|
||||
surface: SurfaceData,
|
||||
framebuffers: FramebufferData,
|
||||
|
@ -155,7 +154,7 @@ impl VulkanWindowInner {
|
|||
unsafe fn new(
|
||||
resolutions: ResolutionData,
|
||||
window: &Window,
|
||||
manager: &WindowDataManager,
|
||||
manager: &RendererBackendManager,
|
||||
) -> Self {
|
||||
let surface = SurfaceData::new(window, manager);
|
||||
|
||||
|
@ -411,7 +410,7 @@ impl VulkanWindowInner {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn resize(&mut self, resolutions: ResolutionData, manager: &WindowDataManager) {
|
||||
unsafe fn resize(&mut self, resolutions: ResolutionData, manager: &RendererBackendManager) {
|
||||
self.swapchain.manual_drop(&self.vulkan_data);
|
||||
for framebuffer in &self.framebuffers.framebuffers {
|
||||
self.vulkan_data
|
||||
|
@ -530,8 +529,13 @@ impl VulkanWindowInner {
|
|||
}
|
||||
|
||||
#[allow(unused_variables, clippy::needless_pass_by_ref_mut)]
|
||||
unsafe fn render(&mut self, filter_chain: &mut FilterChain) {
|
||||
let (present_index, _) = self
|
||||
unsafe fn render(
|
||||
&mut self,
|
||||
filter_chain: &mut FilterChain,
|
||||
resolutions: ResolutionData,
|
||||
manager: &RendererBackendManager,
|
||||
) {
|
||||
let (present_index, is_suboptimal) = self
|
||||
.swapchain
|
||||
.swapchain_loader
|
||||
.acquire_next_image(
|
||||
|
@ -541,6 +545,10 @@ impl VulkanWindowInner {
|
|||
vk::Fence::null(),
|
||||
)
|
||||
.unwrap();
|
||||
if is_suboptimal {
|
||||
self.resize(resolutions, manager);
|
||||
return;
|
||||
}
|
||||
let clear_values = [vk::ClearValue {
|
||||
color: vk::ClearColorValue {
|
||||
float32: [0.0, 0.0, 0.0, 0.0],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{mpsc::Sender, Arc, Mutex},
|
||||
sync::{mpsc::Sender, Arc, Mutex, RwLock},
|
||||
};
|
||||
|
||||
use gb_emu_lib::connect::{EmulatorMessage, JoypadState, Renderer};
|
||||
|
@ -22,9 +22,9 @@ use winit_input_helper::WinitInputHelper;
|
|||
#[cfg_attr(feature = "vulkan", path = "renderer/vulkan/vulkan.rs")]
|
||||
mod renderer;
|
||||
|
||||
use renderer::WindowData;
|
||||
use renderer::RendererBackend;
|
||||
|
||||
use self::renderer::{WindowDataManager, WindowOptions};
|
||||
use self::renderer::{RendererBackendManager, WindowOptions};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ResolutionData {
|
||||
|
@ -36,13 +36,19 @@ pub struct ResolutionData {
|
|||
|
||||
pub struct WindowInfo {
|
||||
id: WindowId,
|
||||
data: Arc<Mutex<WindowData>>,
|
||||
data: Arc<WindowData>,
|
||||
}
|
||||
|
||||
struct WindowData {
|
||||
renderer: Mutex<RendererBackend>,
|
||||
window: Window,
|
||||
real_factor: RwLock<u32>,
|
||||
}
|
||||
|
||||
pub struct WindowManager {
|
||||
event_loop: EventLoop<()>,
|
||||
windows: HashMap<WindowId, Arc<Mutex<WindowData>>>,
|
||||
window_data_manager: Arc<WindowDataManager>,
|
||||
windows: HashMap<WindowId, Arc<WindowData>>,
|
||||
window_data_manager: Arc<RendererBackendManager>,
|
||||
input: Arc<Mutex<WinitInputHelper>>,
|
||||
sender: Sender<EmulatorMessage>,
|
||||
}
|
||||
|
@ -51,9 +57,10 @@ impl WindowManager {
|
|||
pub(crate) fn new(sender: Sender<EmulatorMessage>) -> Self {
|
||||
let event_loop = EventLoop::new();
|
||||
#[cfg(feature = "vulkan")]
|
||||
let window_data_manager = Arc::new(WindowDataManager::new(event_loop.raw_display_handle()));
|
||||
let window_data_manager =
|
||||
Arc::new(RendererBackendManager::new(event_loop.raw_display_handle()));
|
||||
#[cfg(feature = "pixels")]
|
||||
let window_data_manager = Arc::new(WindowDataManager::new());
|
||||
let window_data_manager = Arc::new(RendererBackendManager::new());
|
||||
Self {
|
||||
event_loop,
|
||||
windows: HashMap::new(),
|
||||
|
@ -94,8 +101,19 @@ impl WindowManager {
|
|||
}
|
||||
Event::RedrawRequested(window_id) => {
|
||||
if let Some(w) = self.windows.get(&window_id) {
|
||||
if let Ok(mut data) = w.lock() {
|
||||
data.render();
|
||||
if let Ok(mut renderer) = w.renderer.lock() {
|
||||
let inner_size = w.window.inner_size();
|
||||
if let Ok(real_factor) = w.real_factor.read() {
|
||||
renderer.render(
|
||||
ResolutionData {
|
||||
real_width: inner_size.width,
|
||||
real_height: inner_size.height,
|
||||
scaled_width: inner_size.width / *real_factor,
|
||||
scaled_height: inner_size.height / *real_factor,
|
||||
},
|
||||
&self.window_data_manager,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,13 +124,11 @@ impl WindowManager {
|
|||
}
|
||||
|
||||
pub struct WindowRenderer {
|
||||
window: Window,
|
||||
data: Arc<WindowData>,
|
||||
input: Arc<Mutex<WinitInputHelper>>,
|
||||
data: Arc<Mutex<WindowData>>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
factor: usize,
|
||||
real_factor: u32,
|
||||
gamepad_handler: Option<Gilrs>,
|
||||
joypad_state: JoypadState,
|
||||
current_rumble: bool,
|
||||
|
@ -124,7 +140,7 @@ impl WindowRenderer {
|
|||
gamepad_handler: Option<Gilrs>,
|
||||
input: Arc<Mutex<WinitInputHelper>>,
|
||||
event_loop: &EventLoop<()>,
|
||||
manager: Arc<WindowDataManager>,
|
||||
manager: Arc<RendererBackendManager>,
|
||||
) -> (Self, WindowInfo) {
|
||||
let window = WindowBuilder::new()
|
||||
.with_title("Gameboy")
|
||||
|
@ -147,26 +163,27 @@ impl WindowRenderer {
|
|||
),
|
||||
};
|
||||
|
||||
let data = Arc::new(Mutex::new(WindowData::new(
|
||||
resolutions,
|
||||
&window,
|
||||
options,
|
||||
manager,
|
||||
)));
|
||||
let renderer = Mutex::new(RendererBackend::new(resolutions, &window, options, manager));
|
||||
let id = window.id();
|
||||
|
||||
let data = Arc::new(WindowData {
|
||||
renderer,
|
||||
window,
|
||||
real_factor: RwLock::new(real_factor),
|
||||
});
|
||||
|
||||
let info = WindowInfo {
|
||||
id: window.id(),
|
||||
id,
|
||||
data: data.clone(),
|
||||
};
|
||||
|
||||
(
|
||||
Self {
|
||||
window,
|
||||
input,
|
||||
data,
|
||||
input,
|
||||
width: 0,
|
||||
height: 0,
|
||||
factor,
|
||||
real_factor,
|
||||
gamepad_handler,
|
||||
joypad_state: JoypadState::default(),
|
||||
current_rumble: false,
|
||||
|
@ -180,12 +197,18 @@ impl Renderer<[u8; 4]> for WindowRenderer {
|
|||
fn prepare(&mut self, width: usize, height: usize) {
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self.real_factor = (self.window.scale_factor() * self.factor as f64) as u32;
|
||||
|
||||
let real_width = (width as u32) * self.real_factor;
|
||||
let real_height = (height as u32) * self.real_factor;
|
||||
let real_factor = (self.data.window.scale_factor() * self.factor as f64) as u32;
|
||||
|
||||
self.window
|
||||
let real_width = (width as u32) * real_factor;
|
||||
let real_height = (height as u32) * real_factor;
|
||||
|
||||
if let Ok(mut f) = self.data.real_factor.write() {
|
||||
*f = real_factor;
|
||||
}
|
||||
|
||||
self.data
|
||||
.window
|
||||
.set_inner_size(PhysicalSize::new(real_width, real_height));
|
||||
|
||||
let resolutions = ResolutionData {
|
||||
|
@ -195,21 +218,21 @@ impl Renderer<[u8; 4]> for WindowRenderer {
|
|||
scaled_height: height as u32,
|
||||
};
|
||||
|
||||
if let Ok(mut data) = self.data.lock() {
|
||||
data.resize(resolutions, &self.window);
|
||||
if let Ok(mut data) = self.data.renderer.lock() {
|
||||
data.resize(resolutions, &self.data.window);
|
||||
}
|
||||
self.window.request_redraw();
|
||||
self.data.window.request_redraw();
|
||||
}
|
||||
|
||||
fn display(&mut self, buffer: &[[u8; 4]]) {
|
||||
if let Ok(mut data) = self.data.lock() {
|
||||
if let Ok(mut data) = self.data.renderer.lock() {
|
||||
data.new_frame(buffer);
|
||||
}
|
||||
self.window.request_redraw();
|
||||
self.data.window.request_redraw();
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: String) {
|
||||
self.window.set_title(&title);
|
||||
self.data.window.set_title(&title);
|
||||
}
|
||||
|
||||
fn latest_joypad_state(&mut self) -> JoypadState {
|
||||
|
|
Loading…
Add table
Reference in a new issue