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