Automatically remap controllers; separate cxxbridge build files

This commit is contained in:
Luke Street 2022-02-09 00:13:19 -05:00
parent ed4d38073b
commit 8286f006cf
15 changed files with 743 additions and 689 deletions

View File

@ -31,24 +31,24 @@ fn main() {
let cxx_flag = "-std=c++17"; let cxx_flag = "-std=c++17";
#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))] #[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
let cxx_flag = "-std=gnu++17"; let cxx_flag = "-std=gnu++17";
cxx_build::bridge("src/lib.rs") cxx_build::bridge("src/cxxbridge.rs")
.include("include") .include("include")
.include(zeus_include.clone()) .include(zeus_include.clone())
.flag(cxx_flag) .flag(cxx_flag)
.compile("aurora"); .compile("aurora");
println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=src/cxxbridge.rs");
cxx_build::bridge("src/shaders/mod.rs") cxx_build::bridge("src/shaders/cxxbridge.rs")
.include("include") .include("include")
.include(zeus_include.clone()) .include(zeus_include.clone())
.flag(cxx_flag) .flag(cxx_flag)
.compile("aurora_shaders"); .compile("aurora_shaders");
println!("cargo:rerun-if-changed=src/shaders/mod.rs"); println!("cargo:rerun-if-changed=src/shaders/cxxbridge.rs");
cxx_build::bridge("src/imgui.rs") cxx_build::bridge("src/imgui/cxxbridge.rs")
.include("include") .include("include")
.include(zeus_include.clone()) .include(zeus_include.clone())
.include(imgui_include.clone()) .include(imgui_include.clone())
.include(imgui_engine_include.clone()) .include(imgui_engine_include.clone())
.flag(cxx_flag) .flag(cxx_flag)
.compile("aurora_imgui"); .compile("aurora_imgui");
println!("cargo:rerun-if-changed=src/imgui.rs"); println!("cargo:rerun-if-changed=src/imgui/cxxbridge.rs");
} }

200
Graphics/src/cxxbridge.rs Normal file
View File

@ -0,0 +1,200 @@
use sdl2::controller::{Axis, Button};
use crate::{
app_run, get_args, get_backend, get_backend_string, get_dxt_compression_supported,
get_window_size,
sdl::{get_controller_player_index, set_controller_player_index},
set_fullscreen, set_window_title, App, WindowContext,
};
#[cxx::bridge(namespace = "aurora")]
pub(crate) mod ffi {
unsafe extern "C++" {
include!("aurora.hpp");
pub(crate) type AppDelegate;
}
unsafe extern "C++" {
include!("lib.hpp");
pub(crate) fn App_onAppLaunched(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppIdle(cb: Pin<&mut AppDelegate>, dt: f32) -> bool;
pub(crate) fn App_onAppDraw(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppPostDraw(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppWindowResized(cb: Pin<&mut AppDelegate>, size: &WindowSize);
pub(crate) fn App_onAppWindowMoved(cb: Pin<&mut AppDelegate>, x: i32, y: i32);
pub(crate) fn App_onAppExiting(cb: Pin<&mut AppDelegate>);
// Input
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
pub(crate) fn App_onCharKeyUp(cb: Pin<&mut AppDelegate>, code: u8);
pub(crate) fn App_onSpecialKeyDown(
cb: Pin<&mut AppDelegate>,
key: SpecialKey,
is_repeat: bool,
);
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: SpecialKey);
// Controller
pub(crate) fn App_onControllerButton(
cb: Pin<&mut AppDelegate>,
idx: u32,
button: ControllerButton,
pressed: bool,
);
pub(crate) fn App_onControllerAxis(
cb: Pin<&mut AppDelegate>,
idx: u32,
axis: ControllerAxis,
value: i16,
);
}
pub struct Window {
pub(crate) inner: Box<WindowContext>,
}
pub struct WindowSize {
pub width: u32,
pub height: u32,
}
#[derive(Debug)]
pub enum Backend {
Invalid,
Vulkan,
Metal,
D3D12,
D3D11,
OpenGL,
WebGPU,
}
pub enum ElementState {
Pressed,
Released,
}
pub enum MouseButton {
Left,
Right,
Middle,
Other,
}
pub enum SpecialKey {
None = 0,
F1 = 1,
F2 = 2,
F3 = 3,
F4 = 4,
F5 = 5,
F6 = 6,
F7 = 7,
F8 = 8,
F9 = 9,
F10 = 10,
F11 = 11,
F12 = 12,
Esc = 13,
Enter = 14,
Backspace = 15,
Insert = 16,
Delete = 17,
Home = 18,
End = 19,
PgUp = 20,
PgDown = 21,
Left = 22,
Right = 23,
Up = 24,
Down = 25,
Tab = 26,
}
pub struct KeyboardInput {
pub scancode: u32,
pub state: ElementState,
// pub
}
pub enum ControllerButton {
A,
B,
X,
Y,
Back,
Guide,
Start,
LeftStick,
RightStick,
LeftShoulder,
RightShoulder,
DPadUp,
DPadDown,
DPadLeft,
DPadRight,
Other,
MAX,
}
pub enum ControllerAxis {
LeftX,
LeftY,
RightX,
RightY,
TriggerLeft,
TriggerRight,
MAX,
}
pub struct Icon {
pub data: Vec<u8>,
pub width: u32,
pub height: u32,
}
extern "Rust" {
type WindowContext;
type App;
fn app_run(mut delegate: UniquePtr<AppDelegate>, icon: Icon);
fn get_args() -> Vec<String>;
fn get_window_size() -> WindowSize;
fn set_window_title(title: &CxxString);
fn get_dxt_compression_supported() -> bool;
fn get_backend() -> Backend;
fn get_backend_string() -> &'static str;
fn set_fullscreen(v: bool);
fn get_controller_player_index(which: u32) -> i32;
fn set_controller_player_index(which: u32, index: i32);
}
}
impl From<Button> for ffi::ControllerButton {
fn from(button: Button) -> Self {
match button {
Button::A => ffi::ControllerButton::A,
Button::B => ffi::ControllerButton::B,
Button::X => ffi::ControllerButton::X,
Button::Y => ffi::ControllerButton::Y,
Button::Back => ffi::ControllerButton::Back,
Button::Guide => ffi::ControllerButton::Guide,
Button::Start => ffi::ControllerButton::Start,
Button::LeftStick => ffi::ControllerButton::LeftStick,
Button::RightStick => ffi::ControllerButton::RightStick,
Button::LeftShoulder => ffi::ControllerButton::LeftShoulder,
Button::RightShoulder => ffi::ControllerButton::RightShoulder,
Button::DPadUp => ffi::ControllerButton::DPadUp,
Button::DPadDown => ffi::ControllerButton::DPadDown,
Button::DPadLeft => ffi::ControllerButton::DPadLeft,
Button::DPadRight => ffi::ControllerButton::DPadRight,
_ => ffi::ControllerButton::Other,
}
}
}
impl From<Axis> for ffi::ControllerAxis {
fn from(axis: Axis) -> Self {
match axis {
Axis::LeftX => ffi::ControllerAxis::LeftX,
Axis::LeftY => ffi::ControllerAxis::LeftY,
Axis::RightX => ffi::ControllerAxis::RightX,
Axis::RightY => ffi::ControllerAxis::RightY,
Axis::TriggerLeft => ffi::ControllerAxis::TriggerLeft,
Axis::TriggerRight => ffi::ControllerAxis::TriggerRight,
}
}
}

View File

@ -0,0 +1,25 @@
use crate::{
gpu::DeviceHolder,
imgui::{ImGuiEngine_AddTexture, ImGuiState},
};
#[cxx::bridge(namespace = "metaforce")]
pub(crate) mod ffi {
unsafe extern "C++" {
include!("ImGuiEngine.hpp");
pub(crate) fn ImGuiEngine_Initialize(scale: f32);
pub(crate) fn ImGuiEngine_AddTextures(state: &mut ImGuiState, device: &DeviceHolder);
}
extern "Rust" {
type ImGuiState;
type DeviceHolder;
fn ImGuiEngine_AddTexture(
state: &mut ImGuiState,
device: &DeviceHolder,
width: u32,
height: u32,
data: &[u8],
) -> usize;
}
}

View File

@ -1,25 +1,8 @@
use cxxbridge::ffi;
use crate::{gpu::DeviceHolder, imgui_backend}; use crate::{gpu::DeviceHolder, imgui_backend};
#[cxx::bridge(namespace = "metaforce")] mod cxxbridge;
mod ffi {
unsafe extern "C++" {
include!("ImGuiEngine.hpp");
pub(crate) fn ImGuiEngine_Initialize(scale: f32);
pub(crate) fn ImGuiEngine_AddTextures(state: &mut ImGuiState, device: &DeviceHolder);
}
extern "Rust" {
type ImGuiState;
type DeviceHolder;
fn ImGuiEngine_AddTexture(
state: &mut ImGuiState,
device: &DeviceHolder,
width: u32,
height: u32,
data: &[u8],
) -> usize;
}
}
pub struct ImGuiState { pub struct ImGuiState {
pub(crate) context: imgui::Context, pub(crate) context: imgui::Context,

View File

@ -3,8 +3,12 @@
#![allow(unused_variables)] #![allow(unused_variables)]
#![allow(unused_unsafe)] #![allow(unused_unsafe)]
use std::{collections::HashMap, time::Instant}; use std::{
collections::{BTreeMap, HashMap},
time::Instant,
};
use cxxbridge::ffi;
use sdl2::{ use sdl2::{
controller::{Axis, Button, GameController}, controller::{Axis, Button, GameController},
event::Event as SDLEvent, event::Event as SDLEvent,
@ -17,220 +21,29 @@ use winit::{
}; };
use crate::{ use crate::{
ffi::{SpecialKey, WindowSize},
gpu::{create_depth_texture, create_render_texture, initialize_gpu, DeviceHolder}, gpu::{create_depth_texture, create_render_texture, initialize_gpu, DeviceHolder},
imgui::{initialize_imgui, ImGuiState}, imgui::{initialize_imgui, ImGuiState},
sdl::{
get_controller_player_index, initialize_sdl, poll_sdl_events, remap_controller_layout,
set_controller_player_index, SdlState,
},
shaders::render_into_pass, shaders::render_into_pass,
}; };
mod cxxbridge;
mod gpu; mod gpu;
mod imgui; mod imgui;
mod imgui_backend; mod imgui_backend;
mod sdl;
mod shaders; mod shaders;
mod util; mod util;
mod zeus; mod zeus;
#[cxx::bridge(namespace = "aurora")]
mod ffi {
unsafe extern "C++" {
include!("aurora.hpp");
pub(crate) type AppDelegate;
}
unsafe extern "C++" {
include!("lib.hpp");
pub(crate) fn App_onAppLaunched(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppIdle(cb: Pin<&mut AppDelegate>, dt: f32) -> bool;
pub(crate) fn App_onAppDraw(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppPostDraw(cb: Pin<&mut AppDelegate>);
pub(crate) fn App_onAppWindowResized(cb: Pin<&mut AppDelegate>, size: &WindowSize);
pub(crate) fn App_onAppWindowMoved(cb: Pin<&mut AppDelegate>, x: i32, y: i32);
pub(crate) fn App_onAppExiting(cb: Pin<&mut AppDelegate>);
// Input
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
pub(crate) fn App_onCharKeyUp(cb: Pin<&mut AppDelegate>, code: u8);
pub(crate) fn App_onSpecialKeyDown(
cb: Pin<&mut AppDelegate>,
key: SpecialKey,
is_repeat: bool,
);
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: SpecialKey);
// Controller
pub(crate) fn App_onControllerButton(
cb: Pin<&mut AppDelegate>,
idx: u32,
button: ControllerButton,
pressed: bool,
);
pub(crate) fn App_onControllerAxis(
cb: Pin<&mut AppDelegate>,
idx: u32,
axis: ControllerAxis,
value: i16,
);
}
pub struct Window {
pub(crate) inner: Box<WindowContext>,
}
pub struct WindowSize {
pub width: u32,
pub height: u32,
}
#[derive(Debug)]
pub enum Backend {
Invalid,
Vulkan,
Metal,
D3D12,
D3D11,
OpenGL,
WebGPU,
}
pub enum ElementState {
Pressed,
Released,
}
pub enum MouseButton {
Left,
Right,
Middle,
Other,
}
pub enum SpecialKey {
None = 0,
F1 = 1,
F2 = 2,
F3 = 3,
F4 = 4,
F5 = 5,
F6 = 6,
F7 = 7,
F8 = 8,
F9 = 9,
F10 = 10,
F11 = 11,
F12 = 12,
Esc = 13,
Enter = 14,
Backspace = 15,
Insert = 16,
Delete = 17,
Home = 18,
End = 19,
PgUp = 20,
PgDown = 21,
Left = 22,
Right = 23,
Up = 24,
Down = 25,
Tab = 26,
}
pub struct KeyboardInput {
pub scancode: u32,
pub state: ElementState,
// pub
}
pub enum ControllerButton {
A,
B,
X,
Y,
Back,
Guide,
Start,
LeftStick,
RightStick,
LeftShoulder,
RightShoulder,
DPadUp,
DPadDown,
DPadLeft,
DPadRight,
Other,
MAX,
}
pub enum ControllerAxis {
LeftX,
LeftY,
RightX,
RightY,
TriggerLeft,
TriggerRight,
MAX,
}
pub struct Icon {
pub data: Vec<u8>,
pub width: u32,
pub height: u32,
}
extern "Rust" {
type WindowContext;
type App;
fn app_run(mut delegate: UniquePtr<AppDelegate>, icon: Icon);
fn get_args() -> Vec<String>;
fn get_window_size() -> WindowSize;
fn set_window_title(title: &CxxString);
fn get_dxt_compression_supported() -> bool;
fn get_backend() -> Backend;
fn get_backend_string() -> &'static str;
fn set_fullscreen(v: bool);
fn get_controller_player_index(which: u32) -> i32;
fn set_controller_player_index(which: u32, index: i32);
}
}
impl From<Button> for ffi::ControllerButton {
fn from(button: Button) -> Self {
match button {
Button::A => ffi::ControllerButton::A,
Button::B => ffi::ControllerButton::B,
Button::X => ffi::ControllerButton::X,
Button::Y => ffi::ControllerButton::Y,
Button::Back => ffi::ControllerButton::Back,
Button::Guide => ffi::ControllerButton::Guide,
Button::Start => ffi::ControllerButton::Start,
Button::LeftStick => ffi::ControllerButton::LeftStick,
Button::RightStick => ffi::ControllerButton::RightStick,
Button::LeftShoulder => ffi::ControllerButton::LeftShoulder,
Button::RightShoulder => ffi::ControllerButton::RightShoulder,
Button::DPadUp => ffi::ControllerButton::DPadUp,
Button::DPadDown => ffi::ControllerButton::DPadDown,
Button::DPadLeft => ffi::ControllerButton::DPadLeft,
Button::DPadRight => ffi::ControllerButton::DPadRight,
_ => ffi::ControllerButton::Other,
}
}
}
impl From<Axis> for ffi::ControllerAxis {
fn from(axis: Axis) -> Self {
match axis {
Axis::LeftX => ffi::ControllerAxis::LeftX,
Axis::LeftY => ffi::ControllerAxis::LeftY,
Axis::RightX => ffi::ControllerAxis::RightX,
Axis::RightY => ffi::ControllerAxis::RightY,
Axis::TriggerLeft => ffi::ControllerAxis::TriggerLeft,
Axis::TriggerRight => ffi::ControllerAxis::TriggerRight,
}
}
}
pub struct App { pub struct App {
window: ffi::Window, window: ffi::Window,
gpu: DeviceHolder, gpu: DeviceHolder,
imgui: ImGuiState, imgui: ImGuiState,
// SDL sdl: SdlState,
sdl: Sdl,
sdl_events: sdl2::EventPump,
sdl_controller_sys: GameControllerSubsystem,
sdl_open_controllers: HashMap<u32, GameController>,
} }
pub struct WindowContext { pub struct WindowContext {
@ -246,29 +59,21 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
env_logger::init(); env_logger::init();
log::info!("Running app"); log::info!("Running app");
let event_loop = winit::event_loop::EventLoop::new(); let event_loop = winit::event_loop::EventLoop::new();
let window_icon = winit::window::Icon::from_rgba(icon.data, icon.width, icon.height).expect("Failed to load icon"); let window_icon = winit::window::Icon::from_rgba(icon.data, icon.width, icon.height)
.expect("Failed to load icon");
let window = winit::window::WindowBuilder::new() let window = winit::window::WindowBuilder::new()
.with_inner_size(winit::dpi::LogicalSize::new(1280, 720)) .with_inner_size(winit::dpi::LogicalSize::new(1280, 720))
.with_window_icon(Some(window_icon)) .with_window_icon(Some(window_icon))
.build(&event_loop) .build(&event_loop)
.unwrap(); .unwrap();
let sdl = sdl2::init().unwrap(); let sdl = initialize_sdl();
let sdl_events = sdl.event_pump().unwrap();
let controller = sdl.game_controller().unwrap();
let gpu = initialize_gpu(&window); let gpu = initialize_gpu(&window);
let imgui = initialize_imgui(&window, &gpu); let imgui = initialize_imgui(&window, &gpu);
let mut special_keys_pressed: [bool; 512] = [false; 512]; let mut special_keys_pressed: [bool; 512] = [false; 512];
shaders::construct_state(gpu.device.clone(), gpu.queue.clone(), &gpu.config); shaders::construct_state(gpu.device.clone(), gpu.queue.clone(), &gpu.config);
let app = App { let app =
window: ffi::Window { inner: Box::new(WindowContext { window }) }, App { window: ffi::Window { inner: Box::new(WindowContext { window }) }, gpu, imgui, sdl };
gpu, let window_size = ffi::WindowSize {
imgui,
sdl,
sdl_events,
sdl_controller_sys: controller,
sdl_open_controllers: Default::default(),
};
let window_size = WindowSize {
width: app.gpu.surface_config.width, width: app.gpu.surface_config.width,
height: app.gpu.surface_config.height, height: app.gpu.surface_config.height,
}; };
@ -290,57 +95,10 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
let gpu = &mut app.gpu; let gpu = &mut app.gpu;
// SDL event loop // SDL event loop
for event in app.sdl_events.poll_iter() { if !poll_sdl_events(&mut app.sdl, &mut delegate) {
// log::info!("SDL event: {:?}", event);
match event {
SDLEvent::ControllerDeviceAdded { which, .. } => {
match app.sdl_controller_sys.open(which) {
Ok(controller) => {
log::info!("Opened SDL controller \"{}\"", controller.name());
app.sdl_open_controllers.insert(which, controller);
}
Err(err) => {
log::warn!("Failed to open SDL controller {} ({:?})", which, err);
}
}
// TODO app connected event
}
SDLEvent::ControllerDeviceRemoved { which, .. } => {
app.sdl_open_controllers.remove(&which);
// TODO app disconnected event
}
SDLEvent::ControllerButtonDown { which, button, .. } => unsafe {
ffi::App_onControllerButton(
delegate.as_mut().unwrap_unchecked(),
which,
button.into(),
true,
);
},
SDLEvent::ControllerButtonUp { which, button, .. } => unsafe {
ffi::App_onControllerButton(
delegate.as_mut().unwrap_unchecked(),
which,
button.into(),
false,
);
},
SDLEvent::ControllerAxisMotion { which, axis, value, .. } => unsafe {
ffi::App_onControllerAxis(
delegate.as_mut().unwrap_unchecked(),
which,
axis.into(),
value,
);
},
// SDL overrides exit signals
SDLEvent::Quit { .. } => {
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
return; return;
} }
_ => {}
}
}
// winit event loop // winit event loop
*control_flow = ControlFlow::Poll; *control_flow = ControlFlow::Poll;
@ -361,7 +119,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
&app.gpu.surface_config, &app.gpu.surface_config,
&app.gpu.config, &app.gpu.config,
); );
let window_size = WindowSize { let window_size = ffi::WindowSize {
width: app.gpu.surface_config.width, width: app.gpu.surface_config.width,
height: app.gpu.surface_config.height, height: app.gpu.surface_config.height,
}; };
@ -382,35 +140,35 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
} => { } => {
// TODO: Handle normal keys, this will require a refactor in game runtime code // TODO: Handle normal keys, this will require a refactor in game runtime code
let special_key = match key { let special_key = match key {
VirtualKeyCode::F1 => SpecialKey::F1, VirtualKeyCode::F1 => ffi::SpecialKey::F1,
VirtualKeyCode::F2 => SpecialKey::F2, VirtualKeyCode::F2 => ffi::SpecialKey::F2,
VirtualKeyCode::F3 => SpecialKey::F3, VirtualKeyCode::F3 => ffi::SpecialKey::F3,
VirtualKeyCode::F4 => SpecialKey::F4, VirtualKeyCode::F4 => ffi::SpecialKey::F4,
VirtualKeyCode::F5 => SpecialKey::F5, VirtualKeyCode::F5 => ffi::SpecialKey::F5,
VirtualKeyCode::F6 => SpecialKey::F6, VirtualKeyCode::F6 => ffi::SpecialKey::F6,
VirtualKeyCode::F7 => SpecialKey::F7, VirtualKeyCode::F7 => ffi::SpecialKey::F7,
VirtualKeyCode::F8 => SpecialKey::F8, VirtualKeyCode::F8 => ffi::SpecialKey::F8,
VirtualKeyCode::F9 => SpecialKey::F9, VirtualKeyCode::F9 => ffi::SpecialKey::F9,
VirtualKeyCode::F10 => SpecialKey::F10, VirtualKeyCode::F10 => ffi::SpecialKey::F10,
VirtualKeyCode::F11 => SpecialKey::F11, VirtualKeyCode::F11 => ffi::SpecialKey::F11,
VirtualKeyCode::F12 => SpecialKey::F12, VirtualKeyCode::F12 => ffi::SpecialKey::F12,
VirtualKeyCode::Escape => SpecialKey::Esc, VirtualKeyCode::Escape => ffi::SpecialKey::Esc,
VirtualKeyCode::Return => SpecialKey::Enter, VirtualKeyCode::Return => ffi::SpecialKey::Enter,
VirtualKeyCode::Back => SpecialKey::Backspace, VirtualKeyCode::Back => ffi::SpecialKey::Backspace,
VirtualKeyCode::Insert => SpecialKey::Insert, VirtualKeyCode::Insert => ffi::SpecialKey::Insert,
VirtualKeyCode::Delete => SpecialKey::Delete, VirtualKeyCode::Delete => ffi::SpecialKey::Delete,
VirtualKeyCode::Home => SpecialKey::Home, VirtualKeyCode::Home => ffi::SpecialKey::Home,
VirtualKeyCode::PageUp => SpecialKey::PgUp, VirtualKeyCode::PageUp => ffi::SpecialKey::PgUp,
VirtualKeyCode::PageDown => SpecialKey::PgDown, VirtualKeyCode::PageDown => ffi::SpecialKey::PgDown,
VirtualKeyCode::Left => SpecialKey::Left, VirtualKeyCode::Left => ffi::SpecialKey::Left,
VirtualKeyCode::Right => SpecialKey::Right, VirtualKeyCode::Right => ffi::SpecialKey::Right,
VirtualKeyCode::Up => SpecialKey::Up, VirtualKeyCode::Up => ffi::SpecialKey::Up,
VirtualKeyCode::Down => SpecialKey::Down, VirtualKeyCode::Down => ffi::SpecialKey::Down,
VirtualKeyCode::Tab => SpecialKey::Tab, VirtualKeyCode::Tab => ffi::SpecialKey::Tab,
_ => SpecialKey::None, _ => ffi::SpecialKey::None,
}; };
if special_key != SpecialKey::None { if special_key != ffi::SpecialKey::None {
let pressed = state == ElementState::Pressed; let pressed = state == ElementState::Pressed;
let repeat = special_keys_pressed[key as usize] == pressed; let repeat = special_keys_pressed[key as usize] == pressed;
special_keys_pressed[key as usize] = pressed; special_keys_pressed[key as usize] = pressed;
@ -596,25 +354,3 @@ fn set_fullscreen(v: bool) {
None None
}); });
} }
fn get_controller_player_index(which: u32) -> i32 {
let mut result: i32 = -1;
for (key, value) in &get_app().sdl_open_controllers {
if value.instance_id() == which {
result = value.player_index();
break;
}
}
result as i32
}
fn set_controller_player_index(which: u32, index: i32) {
for (key, value) in &get_app().sdl_open_controllers {
if value.instance_id() == which {
value.set_player_index(index);
break;
}
}
}

137
Graphics/src/sdl.rs Normal file
View File

@ -0,0 +1,137 @@
use std::collections::{BTreeMap, HashMap};
use sdl2::{
controller::{Axis, GameController},
event::Event,
GameControllerSubsystem, Sdl,
};
use crate::{cxxbridge::ffi, get_app};
pub(crate) struct SdlState {
context: Sdl,
events: sdl2::EventPump,
controller_sys: GameControllerSubsystem,
open_controllers: HashMap<u32, GameController>,
}
pub(crate) fn initialize_sdl() -> SdlState {
let context = sdl2::init().unwrap();
let events = context.event_pump().unwrap();
let controller_sys = context.game_controller().unwrap();
SdlState { context, events, controller_sys, open_controllers: Default::default() }
}
pub(crate) fn poll_sdl_events(
state: &mut SdlState,
delegate: &mut cxx::UniquePtr<ffi::AppDelegate>,
) -> bool {
for event in state.events.poll_iter() {
match event {
Event::ControllerDeviceAdded { which, .. } => {
match state.controller_sys.open(which) {
Ok(controller) => {
log::info!("Opened SDL controller \"{}\"", controller.name());
if let Some(new_mapping) = remap_controller_layout(controller.mapping()) {
state
.controller_sys
.add_mapping(new_mapping.as_str())
.expect("Failed to overwrite mapping");
}
state.open_controllers.insert(controller.instance_id(), controller);
}
Err(err) => {
log::warn!("Failed to open SDL controller {} ({:?})", which, err);
}
}
// TODO app connected event
}
Event::ControllerDeviceRemoved { which, .. } => {
state.open_controllers.remove(&which);
// TODO app disconnected event
}
Event::ControllerButtonDown { which, button, .. } => unsafe {
ffi::App_onControllerButton(
delegate.as_mut().unwrap_unchecked(),
which,
button.into(),
true,
);
},
Event::ControllerButtonUp { which, button, .. } => unsafe {
ffi::App_onControllerButton(
delegate.as_mut().unwrap_unchecked(),
which,
button.into(),
false,
);
},
Event::ControllerAxisMotion { which, axis, value, .. } => unsafe {
ffi::App_onControllerAxis(
delegate.as_mut().unwrap_unchecked(),
which,
axis.into(),
value,
);
},
// SDL overrides exit signals
Event::Quit { .. } => {
return false;
}
_ => {}
}
}
return true;
}
fn remap_controller_layout(mapping: String) -> Option<String> {
let mut new_mapping = String::with_capacity(mapping.len());
let mut entries = BTreeMap::<&str, &str>::new();
for (i, v) in mapping.split(',').enumerate() {
if i < 2 {
if i > 0 {
new_mapping.push(',');
}
new_mapping.push_str(v);
continue;
}
let split = v.splitn(2, ':').collect::<Vec<&str>>();
if split.len() != 2 {
panic!("Invalid mapping entry: {}", v);
}
entries.insert(split[0], split[1]);
}
if entries.contains_key("rightshoulder") && !entries.contains_key("leftshoulder") {
log::debug!("Remapping GameCube controller layout");
// TODO trigger buttons may differ per platform
entries.insert("leftshoulder", "b11");
let z_button = entries.insert("rightshoulder", "b10").unwrap();
entries.insert("back", z_button);
} else if entries.contains_key("leftshoulder")
&& entries.contains_key("rightshoulder")
&& entries.contains_key("back")
{
log::debug!("Controller has standard layout");
return None;
} else {
log::error!("Controller has unsupported layout: {}", mapping);
return None;
}
for (k, v) in entries {
new_mapping.push(',');
new_mapping.push_str(k);
new_mapping.push(':');
new_mapping.push_str(v);
}
return Some(new_mapping);
}
pub(crate) fn get_controller_player_index(which: u32) -> i32 {
get_app().sdl.open_controllers.get(&which).map_or(-1, |c| c.player_index())
}
pub(crate) fn set_controller_player_index(which: u32, index: i32) {
if let Some(c) = get_app().sdl.open_controllers.get(&which) {
c.set_player_index(index);
}
}

View File

@ -40,6 +40,7 @@ pub(crate) fn construct_state(
device: &wgpu::Device, device: &wgpu::Device,
_queue: &wgpu::Queue, _queue: &wgpu::Queue,
buffers: &BuiltBuffers, buffers: &BuiltBuffers,
graphics_config: &GraphicsConfig,
) -> State { ) -> State {
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl")); let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
let uniform_size = wgpu::BufferSize::new(std::mem::size_of::<Uniform>() as u64); let uniform_size = wgpu::BufferSize::new(std::mem::size_of::<Uniform>() as u64);

View File

@ -0,0 +1,253 @@
use crate::shaders::{
aabb::queue_aabb,
fog_volume_filter::queue_fog_volume_filter,
fog_volume_plane::queue_fog_volume_plane,
model::{add_material_set, add_model},
movie_player::queue_movie_player,
resolve_color, resolve_depth, set_scissor, set_viewport,
texture::{
create_dynamic_texture_2d, create_render_texture, create_static_texture_2d, drop_texture,
write_texture,
},
textured_quad::{queue_textured_quad, queue_textured_quad_verts},
update_fog_state, update_model_view, update_projection,
};
#[cxx::bridge]
pub(crate) mod ffi {
unsafe extern "C++" {
include!("zeus/CVector2f.hpp");
include!("zeus/CVector3f.hpp");
include!("zeus/CVector4f.hpp");
include!("zeus/CMatrix4f.hpp");
include!("zeus/CColor.hpp");
include!("zeus/CRectangle.hpp");
include!("zeus/CAABox.hpp");
#[namespace = "zeus"]
type CVector2f = crate::zeus::CVector2f;
#[namespace = "zeus"]
type CVector3f = crate::zeus::CVector3f;
#[namespace = "zeus"]
type CVector4f = crate::zeus::CVector4f;
#[namespace = "zeus"]
type CMatrix4f = crate::zeus::CMatrix4f;
#[namespace = "zeus"]
type CColor = crate::zeus::CColor;
#[namespace = "zeus"]
type CRectangle = crate::zeus::CRectangle;
#[namespace = "zeus"]
type CAABox = crate::zeus::CAABox;
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) enum CameraFilterType {
Passthru,
Multiply,
Invert,
Add,
Subtract,
Blend,
Widescreen,
SceneAdd,
NoColor,
InvDstMultiply,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) enum ZTest {
Never,
Less,
Equal,
LEqual,
Greater,
NEqual,
GEqual,
Always,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) enum TextureFormat {
RGBA8,
R8,
R32Float,
DXT1,
DXT3,
DXT5,
BPTC,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) enum TextureClampMode {
Repeat,
ClampToEdge,
ClampToWhite,
ClampToBlack,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) struct TextureRef {
pub(crate) id: u32,
pub(crate) render: bool,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub(crate) enum FogMode {
None = 0x00,
PerspLin = 0x02,
PerspExp = 0x04,
PerspExp2 = 0x05,
PerspRevExp = 0x06,
PerspRevExp2 = 0x07,
OrthoLin = 0x0A,
OrthoExp = 0x0C,
OrthoExp2 = 0x0D,
OrthoRevExp = 0x0E,
OrthoRevExp2 = 0x0F,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct FogState {
#[cxx_name = "m_color"]
pub(crate) color: CColor,
#[cxx_name = "m_A"]
pub(crate) a: f32,
#[cxx_name = "m_B"]
pub(crate) b: f32,
#[cxx_name = "m_C"]
pub(crate) c: f32,
#[cxx_name = "m_mode"]
pub(crate) mode: FogMode,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct ClipRect {
x: i32,
y: i32,
width: i32,
height: i32,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct MaterialPassInfo {
tex_idx: u32,
constant_color: CColor,
has_constant_color: bool, // would love to use Option...
uv_source: u8,
uv_anim_type: u8,
uv_anim_params: [f32; 9],
normalize: bool, // TODO might be static based on uv type?
sample_alpha: bool,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Clone)]
pub(crate) struct MaterialInfo {
pass_info: [MaterialPassInfo; 8],
texture_ids: Vec<TextureRef>,
shader_type: u8,
blend_mode: u8,
}
#[namespace = "aurora::shaders"]
extern "Rust" {
fn update_model_view(mv: CMatrix4f, mv_inv: CMatrix4f);
fn update_projection(proj: CMatrix4f);
fn update_fog_state(state: FogState);
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32);
fn set_scissor(x: u32, y: u32, w: u32, h: u32);
fn resolve_color(rect: ClipRect, bind: u32, clear_depth: bool);
fn resolve_depth(rect: ClipRect, bind: u32);
fn add_material_set(materials: Vec<MaterialInfo>) -> u32;
fn add_model(verts: &[u8], indices: &[u8]) -> u32;
fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool);
fn queue_fog_volume_plane(verts: &CxxVector<CVector4f>, pass: u8);
fn queue_fog_volume_filter(color: CColor, two_way: bool);
fn queue_textured_quad_verts(
filter_type: CameraFilterType,
texture: TextureRef,
z_comparison: ZTest,
z_test: bool,
color: CColor,
pos: &[CVector3f],
uvs: &[CVector2f],
lod: f32,
);
fn queue_textured_quad(
filter_type: CameraFilterType,
texture: TextureRef,
z_comparison: ZTest,
z_test: bool,
color: CColor,
uv_scale: f32,
rect: CRectangle,
z: f32,
);
fn queue_movie_player(
tex_y: TextureRef,
tex_u: TextureRef,
tex_v: TextureRef,
color: CColor,
h_pad: f32,
v_pad: f32,
);
fn create_static_texture_2d(
width: u32,
height: u32,
mips: u32,
format: TextureFormat,
data: &[u8],
label: &str,
) -> TextureRef;
fn create_dynamic_texture_2d(
width: u32,
height: u32,
mips: u32,
format: TextureFormat,
label: &str,
) -> TextureRef;
fn create_render_texture(
width: u32,
height: u32,
// clamp_mode: TextureClampMode,
color_bind_count: u32,
depth_bind_count: u32,
label: &str,
) -> TextureRef;
fn write_texture(handle: TextureRef, data: &[u8]);
fn drop_texture(handle: TextureRef);
}
}
unsafe impl bytemuck::Zeroable for ffi::FogMode {}
unsafe impl bytemuck::Pod for ffi::FogMode {}
unsafe impl bytemuck::Zeroable for ffi::FogState {}
unsafe impl bytemuck::Pod for ffi::FogState {}
impl Default for ffi::FogState {
fn default() -> Self {
Self { color: Default::default(), a: 0.0, b: 0.5, c: 0.0, mode: ffi::FogMode::None }
}
}
impl Into<u32> for ffi::TextureFormat {
// noinspection RsUnreachablePatterns
fn into(self) -> u32 {
match self {
ffi::TextureFormat::RGBA8 => 1,
ffi::TextureFormat::R8 => 2,
ffi::TextureFormat::R32Float => 3,
ffi::TextureFormat::DXT1 => 4,
ffi::TextureFormat::DXT3 => 5,
ffi::TextureFormat::DXT5 => 6,
ffi::TextureFormat::BPTC => 7,
_ => panic!("Invalid texture format {:?}", self),
}
}
}

View File

@ -5,32 +5,20 @@ use std::{
sync::Arc, sync::Arc,
}; };
use aabb::queue_aabb;
use bytemuck::Pod; use bytemuck::Pod;
use bytemuck_derive::{Pod, Zeroable}; use bytemuck_derive::{Pod, Zeroable};
use cxx::{type_id, ExternType}; use cxx::ExternType;
use fog_volume_filter::queue_fog_volume_filter; use cxxbridge::ffi;
use fog_volume_plane::queue_fog_volume_plane;
use model::{add_material_set, add_model};
use movie_player::queue_movie_player;
use texture::{
create_dynamic_texture_2d, create_render_texture, create_static_texture_2d, drop_texture,
write_texture,
};
use textured_quad::{queue_textured_quad, queue_textured_quad_verts};
use twox_hash::Xxh3Hash64; use twox_hash::Xxh3Hash64;
use wgpu::RenderPipeline;
use crate::{ use crate::{
gpu::GraphicsConfig, gpu::GraphicsConfig,
shaders::{ shaders::texture::{RenderTexture, TextureWithView},
ffi::{TextureFormat, TextureRef},
texture::{RenderTexture, TextureWithView},
},
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, IDENTITY_MATRIX4F}, zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, IDENTITY_MATRIX4F},
}; };
mod aabb; mod aabb;
mod cxxbridge;
mod fog_volume_filter; mod fog_volume_filter;
mod fog_volume_plane; mod fog_volume_plane;
mod model; mod model;
@ -38,245 +26,6 @@ mod movie_player;
mod texture; mod texture;
mod textured_quad; mod textured_quad;
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("zeus/CVector2f.hpp");
include!("zeus/CVector3f.hpp");
include!("zeus/CVector4f.hpp");
include!("zeus/CMatrix4f.hpp");
include!("zeus/CColor.hpp");
include!("zeus/CRectangle.hpp");
include!("zeus/CAABox.hpp");
#[namespace = "zeus"]
type CVector2f = crate::zeus::CVector2f;
#[namespace = "zeus"]
type CVector3f = crate::zeus::CVector3f;
#[namespace = "zeus"]
type CVector4f = crate::zeus::CVector4f;
#[namespace = "zeus"]
type CMatrix4f = crate::zeus::CMatrix4f;
#[namespace = "zeus"]
type CColor = crate::zeus::CColor;
#[namespace = "zeus"]
type CRectangle = crate::zeus::CRectangle;
#[namespace = "zeus"]
type CAABox = crate::zeus::CAABox;
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) enum CameraFilterType {
Passthru,
Multiply,
Invert,
Add,
Subtract,
Blend,
Widescreen,
SceneAdd,
NoColor,
InvDstMultiply,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) enum ZTest {
Never,
Less,
Equal,
LEqual,
Greater,
NEqual,
GEqual,
Always
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) enum TextureFormat {
RGBA8,
R8,
R32Float,
DXT1,
DXT3,
DXT5,
BPTC,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) enum TextureClampMode {
Repeat,
ClampToEdge,
ClampToWhite,
ClampToBlack,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone, Hash)]
pub(crate) struct TextureRef {
pub(crate) id: u32,
pub(crate) render: bool,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub(crate) enum FogMode {
None = 0x00,
PerspLin = 0x02,
PerspExp = 0x04,
PerspExp2 = 0x05,
PerspRevExp = 0x06,
PerspRevExp2 = 0x07,
OrthoLin = 0x0A,
OrthoExp = 0x0C,
OrthoExp2 = 0x0D,
OrthoRevExp = 0x0E,
OrthoRevExp2 = 0x0F,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct FogState {
#[cxx_name = "m_color"]
pub(crate) color: CColor,
#[cxx_name = "m_A"]
pub(crate) a: f32,
#[cxx_name = "m_B"]
pub(crate) b: f32,
#[cxx_name = "m_C"]
pub(crate) c: f32,
#[cxx_name = "m_mode"]
pub(crate) mode: FogMode,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct ClipRect {
x: i32,
y: i32,
width: i32,
height: i32,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Copy, Clone)]
pub(crate) struct MaterialPassInfo {
tex_idx: u32,
constant_color: CColor,
has_constant_color: bool, // would love to use Option...
uv_source: u8,
uv_anim_type: u8,
uv_anim_params: [f32; 9],
normalize: bool, // TODO might be static based on uv type?
sample_alpha: bool,
}
#[namespace = "aurora::shaders"]
#[derive(Debug, Clone)]
pub(crate) struct MaterialInfo {
pass_info: [MaterialPassInfo; 8],
texture_ids: Vec<TextureRef>,
shader_type: u8,
blend_mode: u8,
}
#[namespace = "aurora::shaders"]
extern "Rust" {
fn update_model_view(mv: CMatrix4f, mv_inv: CMatrix4f);
fn update_projection(proj: CMatrix4f);
fn update_fog_state(state: FogState);
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32);
fn set_scissor(x: u32, y: u32, w: u32, h: u32);
fn resolve_color(rect: ClipRect, bind: u32, clear_depth: bool);
fn resolve_depth(rect: ClipRect, bind: u32);
fn add_material_set(materials: Vec<MaterialInfo>) -> u32;
fn add_model(verts: &[u8], indices: &[u8]) -> u32;
fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool);
fn queue_fog_volume_plane(verts: &CxxVector<CVector4f>, pass: u8);
fn queue_fog_volume_filter(color: CColor, two_way: bool);
fn queue_textured_quad_verts(
filter_type: CameraFilterType,
texture: TextureRef,
z_comparison: ZTest,
z_test: bool,
color: CColor,
pos: &[CVector3f],
uvs: &[CVector2f],
lod: f32,
);
fn queue_textured_quad(
filter_type: CameraFilterType,
texture: TextureRef,
z_comparison: ZTest,
z_test: bool,
color: CColor,
uv_scale: f32,
rect: CRectangle,
z: f32,
);
fn queue_movie_player(
tex_y: TextureRef,
tex_u: TextureRef,
tex_v: TextureRef,
color: CColor,
h_pad: f32,
v_pad: f32,
);
fn create_static_texture_2d(
width: u32,
height: u32,
mips: u32,
format: TextureFormat,
data: &[u8],
label: &str,
) -> TextureRef;
fn create_dynamic_texture_2d(
width: u32,
height: u32,
mips: u32,
format: TextureFormat,
label: &str,
) -> TextureRef;
fn create_render_texture(
width: u32,
height: u32,
// clamp_mode: TextureClampMode,
color_bind_count: u32,
depth_bind_count: u32,
label: &str,
) -> TextureRef;
fn write_texture(handle: TextureRef, data: &[u8]);
fn drop_texture(handle: TextureRef);
}
}
unsafe impl bytemuck::Zeroable for ffi::FogMode {}
unsafe impl bytemuck::Pod for ffi::FogMode {}
unsafe impl bytemuck::Zeroable for ffi::FogState {}
unsafe impl bytemuck::Pod for ffi::FogState {}
impl Default for ffi::FogState {
fn default() -> Self {
Self { color: Default::default(), a: 0.0, b: 0.5, c: 0.0, mode: ffi::FogMode::None }
}
}
impl Into<u32> for ffi::TextureFormat {
// noinspection RsUnreachablePatterns
fn into(self) -> u32 {
match self {
TextureFormat::RGBA8 => 1,
TextureFormat::R8 => 2,
TextureFormat::R32Float => 3,
TextureFormat::DXT1 => 4,
TextureFormat::DXT3 => 5,
TextureFormat::DXT5 => 6,
TextureFormat::BPTC => 7,
_ => panic!("Invalid texture format {:?}", self),
}
}
}
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
enum ColoredStripMode { enum ColoredStripMode {
Alpha, Alpha,
@ -397,7 +146,7 @@ pub(crate) fn construct_state(
mapped_at_creation: false, mapped_at_creation: false,
}), }),
}; };
let aabb = aabb::construct_state(&device, &queue, &buffers); let aabb = aabb::construct_state(&device, &queue, &buffers, graphics_config);
let textured_quad = textured_quad::construct_state(&device, &queue, &buffers, graphics_config); let textured_quad = textured_quad::construct_state(&device, &queue, &buffers, graphics_config);
let movie_player = movie_player::construct_state(&device, &queue, &buffers, graphics_config); let movie_player = movie_player::construct_state(&device, &queue, &buffers, graphics_config);
let mut state = RenderState { let mut state = RenderState {
@ -422,6 +171,9 @@ pub(crate) fn construct_state(
for config in textured_quad::INITIAL_PIPELINES { for config in textured_quad::INITIAL_PIPELINES {
construct_pipeline(&mut state, config); construct_pipeline(&mut state, config);
} }
for config in movie_player::INITIAL_PIPELINES {
construct_pipeline(&mut state, config);
}
unsafe { unsafe {
STATE = Some(state); STATE = Some(state);
} }

View File

@ -1,6 +1,6 @@
use std::hash::Hash; use std::hash::Hash;
use crate::shaders::ffi::MaterialInfo; use crate::shaders::cxxbridge::ffi;
struct MaterialShaderData { struct MaterialShaderData {
shader_type: u32, // 5 values (incl. Invalid) shader_type: u32, // 5 values (incl. Invalid)
@ -37,5 +37,5 @@ struct ModelPipelineConfig {
render_alpha_update: bool, render_alpha_update: bool,
} }
pub(crate) fn add_material_set(materials: Vec<MaterialInfo>) -> u32 { return u32::MAX; } pub(crate) fn add_material_set(materials: Vec<ffi::MaterialInfo>) -> u32 { return u32::MAX; }
pub(crate) fn add_model(verts: &[u8], indices: &[u8]) -> u32 { return u32::MAX; } pub(crate) fn add_model(verts: &[u8], indices: &[u8]) -> u32 { return u32::MAX; }

View File

@ -11,14 +11,12 @@ use crate::{
get_app, get_app,
gpu::GraphicsConfig, gpu::GraphicsConfig,
shaders::{ shaders::{
bind_pipeline, bind_pipeline, cxxbridge::ffi, pipeline_ref, push_draw_command, push_uniform, push_verts,
ffi::{CameraFilterType, TextureRef, ZTest}, texture::create_sampler, BuiltBuffers, PipelineCreateCommand, PipelineHolder, PipelineRef,
pipeline_ref, push_draw_command, push_uniform, push_verts, ShaderDrawCommand, STATE,
texture::create_sampler,
BuiltBuffers, PipelineCreateCommand, PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
}, },
util::{align, Vec2, Vec3}, util::{align, Vec2, Vec3},
zeus::{CColor, CMatrix4f, CRectangle, CVector4f}, zeus::{CColor, CMatrix4f},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -216,9 +214,9 @@ struct Vert {
} }
pub(crate) fn queue_movie_player( pub(crate) fn queue_movie_player(
tex_y: TextureRef, tex_y: ffi::TextureRef,
tex_u: TextureRef, tex_u: ffi::TextureRef,
tex_v: TextureRef, tex_v: ffi::TextureRef,
color: CColor, color: CColor,
h_pad: f32, h_pad: f32,
v_pad: f32, v_pad: f32,

View File

@ -10,7 +10,7 @@ use wgpu::{util::DeviceExt, ImageDataLayout};
use crate::{ use crate::{
get_app, get_app,
shaders::{ shaders::{
ffi::{TextureFormat, TextureRef}, cxxbridge::ffi::{TextureFormat, TextureRef},
STATE, STATE,
}, },
}; };

View File

@ -7,11 +7,9 @@ use crate::{
get_app, get_app,
gpu::GraphicsConfig, gpu::GraphicsConfig,
shaders::{ shaders::{
bind_pipeline, bind_pipeline, cxxbridge::ffi, get_combined_matrix, pipeline_ref, push_draw_command,
ffi::{CameraFilterType, TextureRef, ZTest}, push_uniform, push_verts, texture::create_sampler, BuiltBuffers, PipelineCreateCommand,
get_combined_matrix, pipeline_ref, push_draw_command, push_uniform, push_verts, PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
texture::create_sampler,
BuiltBuffers, PipelineCreateCommand, PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
}, },
util::{align, Vec2, Vec3}, util::{align, Vec2, Vec3},
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f}, zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
@ -22,13 +20,13 @@ pub(crate) struct DrawData {
pipeline: PipelineRef, pipeline: PipelineRef,
vert_range: Range<u64>, vert_range: Range<u64>,
uniform_range: Range<u64>, uniform_range: Range<u64>,
texture: TextureRef, texture: ffi::TextureRef,
} }
#[derive(Hash)] #[derive(Hash)]
pub(crate) struct PipelineConfig { pub(crate) struct PipelineConfig {
filter_type: CameraFilterType, filter_type: ffi::CameraFilterType,
z_comparison: ZTest, z_comparison: ffi::ZTest,
z_test: bool, z_test: bool,
} }
pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[ pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[
@ -134,7 +132,7 @@ pub(crate) fn construct_pipeline(
config: &PipelineConfig, config: &PipelineConfig,
) -> PipelineHolder { ) -> PipelineHolder {
let (blend_component, alpha_write) = match config.filter_type { let (blend_component, alpha_write) = match config.filter_type {
CameraFilterType::Multiply => ( ffi::CameraFilterType::Multiply => (
wgpu::BlendComponent { wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::Zero, src_factor: wgpu::BlendFactor::Zero,
dst_factor: wgpu::BlendFactor::Src, dst_factor: wgpu::BlendFactor::Src,
@ -142,7 +140,7 @@ pub(crate) fn construct_pipeline(
}, },
true, true,
), ),
CameraFilterType::Add => ( ffi::CameraFilterType::Add => (
wgpu::BlendComponent { wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha, src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::One, dst_factor: wgpu::BlendFactor::One,
@ -150,7 +148,7 @@ pub(crate) fn construct_pipeline(
}, },
false, false,
), ),
CameraFilterType::Subtract => ( ffi::CameraFilterType::Subtract => (
wgpu::BlendComponent { wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha, src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::One, dst_factor: wgpu::BlendFactor::One,
@ -158,7 +156,7 @@ pub(crate) fn construct_pipeline(
}, },
false, false,
), ),
CameraFilterType::Blend => ( ffi::CameraFilterType::Blend => (
wgpu::BlendComponent { wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha, src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
@ -166,7 +164,7 @@ pub(crate) fn construct_pipeline(
}, },
false, false,
), ),
CameraFilterType::InvDstMultiply => ( ffi::CameraFilterType::InvDstMultiply => (
wgpu::BlendComponent { wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::Zero, src_factor: wgpu::BlendFactor::Zero,
dst_factor: wgpu::BlendFactor::OneMinusSrc, dst_factor: wgpu::BlendFactor::OneMinusSrc,
@ -197,15 +195,15 @@ pub(crate) fn construct_pipeline(
format: graphics.depth_format, format: graphics.depth_format,
depth_write_enabled: config.z_test, depth_write_enabled: config.z_test,
depth_compare: match config.z_comparison { depth_compare: match config.z_comparison {
ZTest::Never => wgpu::CompareFunction::Never, ffi::ZTest::Never => wgpu::CompareFunction::Never,
ZTest::Less => wgpu::CompareFunction::Less, ffi::ZTest::Less => wgpu::CompareFunction::Less,
ZTest::Equal => wgpu::CompareFunction::Equal, ffi::ZTest::Equal => wgpu::CompareFunction::Equal,
ZTest::LEqual => wgpu::CompareFunction::LessEqual, ffi::ZTest::LEqual => wgpu::CompareFunction::LessEqual,
ZTest::Greater => wgpu::CompareFunction::Greater, ffi::ZTest::Greater => wgpu::CompareFunction::Greater,
ZTest::NEqual => wgpu::CompareFunction::NotEqual, ffi::ZTest::NEqual => wgpu::CompareFunction::NotEqual,
ZTest::GEqual => wgpu::CompareFunction::GreaterEqual, ffi::ZTest::GEqual => wgpu::CompareFunction::GreaterEqual,
ZTest::Always => wgpu::CompareFunction::Always, ffi::ZTest::Always => wgpu::CompareFunction::Always,
_=>todo!(), _ => todo!(),
}, },
stencil: Default::default(), stencil: Default::default(),
bias: Default::default(), bias: Default::default(),
@ -251,17 +249,20 @@ struct Vert {
} }
pub(crate) fn queue_textured_quad( pub(crate) fn queue_textured_quad(
filter_type: CameraFilterType, filter_type: ffi::CameraFilterType,
texture: TextureRef, texture: ffi::TextureRef,
z_comparison: ZTest, z_comparison: ffi::ZTest,
z_test: bool, z_test: bool,
color: CColor, color: CColor,
uv_scale: f32, uv_scale: f32,
rect: CRectangle, rect: CRectangle,
z: f32, z: f32,
) { ) {
let pipeline = let pipeline = pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig {
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_comparison, z_test })); filter_type,
z_comparison,
z_test,
}));
let vert_range = push_verts(&[ let vert_range = push_verts(&[
Vert { pos: Vec3::new(0.0, 0.0, z), uv: Vec2::new(0.0, 0.0) }, Vert { pos: Vec3::new(0.0, 0.0, z), uv: Vec2::new(0.0, 0.0) },
Vert { pos: Vec3::new(0.0, 1.0, z), uv: Vec2::new(0.0, uv_scale) }, Vert { pos: Vec3::new(0.0, 1.0, z), uv: Vec2::new(0.0, uv_scale) },
@ -283,9 +284,9 @@ pub(crate) fn queue_textured_quad(
} }
pub(crate) fn queue_textured_quad_verts( pub(crate) fn queue_textured_quad_verts(
filter_type: CameraFilterType, filter_type: ffi::CameraFilterType,
texture: TextureRef, texture: ffi::TextureRef,
z_comparison: ZTest, z_comparison: ffi::ZTest,
z_test: bool, z_test: bool,
color: CColor, color: CColor,
pos: &[CVector3f], pos: &[CVector3f],
@ -296,8 +297,11 @@ pub(crate) fn queue_textured_quad_verts(
panic!("Invalid pos/uv sizes: {}/{}", pos.len(), uvs.len()); panic!("Invalid pos/uv sizes: {}/{}", pos.len(), uvs.len());
} }
let pipeline = let pipeline = pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig {
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_comparison, z_test })); filter_type,
z_comparison,
z_test,
}));
let vert_range = push_verts( let vert_range = push_verts(
&pos.iter() &pos.iter()
.zip(uvs) .zip(uvs)
@ -310,7 +314,7 @@ pub(crate) fn queue_textured_quad_verts(
} }
fn push_textured_quad( fn push_textured_quad(
texture: TextureRef, texture: ffi::TextureRef,
pipeline: PipelineRef, pipeline: PipelineRef,
vert_range: Range<u64>, vert_range: Range<u64>,
uniform_range: Range<u64>, uniform_range: Range<u64>,

View File

@ -1,5 +1,6 @@
use bytemuck_derive::{Pod, Zeroable}; use bytemuck_derive::{Pod, Zeroable};
use cxx::{type_id, ExternType}; use cxx::{type_id, ExternType};
use crate::util::{Vec2, Vec3}; use crate::util::{Vec2, Vec3};
#[derive(Debug, Copy, Clone, Pod, Zeroable, Default)] #[derive(Debug, Copy, Clone, Pod, Zeroable, Default)]
@ -172,57 +173,21 @@ impl From<CMatrix4f> for cgmath::Matrix4<f32> {
} }
impl From<Vec2<f32>> for CVector2f { impl From<Vec2<f32>> for CVector2f {
fn from(v: Vec2<f32>) -> Self { fn from(v: Vec2<f32>) -> Self { Self { x: v.x, y: v.y, _p1: 0.0, _p2: 0.0 } }
Self {
x: v.x,
y: v.y,
_p1: 0.0,
_p2: 0.0
}
}
} }
impl From<CVector2f> for Vec2<f32> { impl From<CVector2f> for Vec2<f32> {
fn from(v: CVector2f) -> Self { fn from(v: CVector2f) -> Self { Self { x: v.x, y: v.y } }
Self {
x: v.x,
y: v.y,
}
}
} }
impl From<&CVector2f> for Vec2<f32> { impl From<&CVector2f> for Vec2<f32> {
fn from(v: &CVector2f) -> Self { fn from(v: &CVector2f) -> Self { Self { x: v.x, y: v.y } }
Self {
x: v.x,
y: v.y,
}
}
} }
impl From<Vec3<f32>> for CVector3f { impl From<Vec3<f32>> for CVector3f {
fn from(v: Vec3<f32>) -> Self { fn from(v: Vec3<f32>) -> Self { Self { x: v.x, y: v.y, z: v.z, _p: 0.0 } }
Self {
x: v.x,
y: v.y,
z: v.z,
_p: 0.0,
}
}
} }
impl From<CVector3f> for Vec3<f32> { impl From<CVector3f> for Vec3<f32> {
fn from(v: CVector3f) -> Self { fn from(v: CVector3f) -> Self { Self { x: v.x, y: v.y, z: v.z } }
Self {
x: v.x,
y: v.y,
z: v.z,
}
}
} }
impl From<&CVector3f> for Vec3<f32> { impl From<&CVector3f> for Vec3<f32> {
fn from(v: &CVector3f) -> Self { fn from(v: &CVector3f) -> Self { Self { x: v.x, y: v.y, z: v.z } }
Self {
x: v.x,
y: v.y,
z: v.z,
}
}
} }