WGPU BACKEND!!! almost works!!
This commit is contained in:
parent
43b800ff80
commit
5a2229728a
112
Cargo.lock
generated
112
Cargo.lock
generated
|
@ -683,15 +683,6 @@ dependencies = [
|
|||
"gb-emu-lib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.20.2"
|
||||
|
@ -1556,6 +1547,7 @@ dependencies = [
|
|||
"ron",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"thiserror",
|
||||
"wgpu",
|
||||
]
|
||||
|
||||
|
@ -1623,7 +1615,7 @@ dependencies = [
|
|||
"vec_map",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"windows 0.52.0",
|
||||
"windows 0.44.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1661,6 +1653,28 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glslang"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5df6491e5d4c222a6373b892c1bea8d697fca0c087890f64f0e2975b3f8bb48"
|
||||
dependencies = [
|
||||
"glslang-sys",
|
||||
"once_cell",
|
||||
"rustc-hash",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glslang-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d76f2d75ad6e8a12c26e77ed6443a9369ef7957daf361e751c3489a97f8b816"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"glob",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.5.0"
|
||||
|
@ -2150,8 +2164,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"librashader-cache",
|
||||
|
@ -2163,12 +2177,13 @@ dependencies = [
|
|||
"librashader-runtime-vk",
|
||||
"librashader-runtime-wgpu",
|
||||
"wgpu",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "librashader-cache"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"blake3",
|
||||
|
@ -2183,8 +2198,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-common"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"num-traits",
|
||||
|
@ -2193,8 +2208,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-preprocess"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"librashader-common",
|
||||
|
@ -2205,8 +2220,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-presets"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"librashader-common",
|
||||
"nom",
|
||||
|
@ -2217,11 +2232,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-reflect"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags 2.4.2",
|
||||
"bytemuck",
|
||||
"glslang",
|
||||
"indexmap 2.1.0",
|
||||
"librashader-common",
|
||||
"librashader-preprocess",
|
||||
|
@ -2232,15 +2248,14 @@ dependencies = [
|
|||
"rspirv",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"shaderc",
|
||||
"spirv",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "librashader-runtime"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"image",
|
||||
|
@ -2254,8 +2269,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-runtime-vk"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"bytemuck",
|
||||
|
@ -2275,8 +2290,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "librashader-runtime-wgpu"
|
||||
version = "0.2.0-beta.5"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#446b052657fee7cc364ae33ba2644fafc65a1587"
|
||||
version = "0.2.0-beta.7"
|
||||
source = "git+https://git.alexjanka.com/alex/librashader#0974254c0e067e4fa8f43f1311a7ac343cec3f2e"
|
||||
dependencies = [
|
||||
"array-concat",
|
||||
"bytemuck",
|
||||
|
@ -3445,15 +3460,6 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b"
|
||||
dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rspirv"
|
||||
version = "0.12.0+sdk-1.3.268.0"
|
||||
|
@ -3662,27 +3668,6 @@ dependencies = [
|
|||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shaderc"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27e07913ada18607bb60d12431cbe3358d3bbebbe95948e1618851dc01e63b7b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"shaderc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shaderc-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73120d240fe22196300f39ca8547ca2d014960f27b19b47b21288b396272f7f7"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
"libc",
|
||||
"roxmltree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
|
@ -4011,7 +3996,6 @@ dependencies = [
|
|||
"nih_plug",
|
||||
"raw-window-handle 0.6.0",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4951,12 +4935,6 @@ version = "0.8.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -8,7 +8,7 @@ description = "Frontend common library for TWINC Game Boy (CGB/DMG) emulator"
|
|||
identifier = "com.alexjanka.TWINC"
|
||||
|
||||
[features]
|
||||
default = ["wgpu", "pixels", "vulkan-static"]
|
||||
default = ["wgpu"]
|
||||
pixels = ["gb-emu-lib/pixels-renderer"]
|
||||
vulkan = ["gb-emu-lib/vulkan-renderer", "gb-emu-lib/vulkan-debug"]
|
||||
vulkan-static = ["vulkan", "gb-emu-lib/vulkan-static"]
|
||||
|
|
|
@ -11,6 +11,7 @@ use cpal::Stream;
|
|||
use gb_emu_lib::{
|
||||
connect::{EmulatorMessage, JoypadState, RendererMessage, ResolutionData},
|
||||
renderer::{RendererBackend, RendererBackendManager},
|
||||
util::PrintErrors,
|
||||
};
|
||||
use gilrs::{Button, Gilrs};
|
||||
use image::ImageBuffer;
|
||||
|
@ -295,12 +296,20 @@ where
|
|||
recording: Option<RecordInfo>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct QueuedBuf {
|
||||
buf: Vec<[u8; 4]>,
|
||||
displayed: bool,
|
||||
}
|
||||
|
||||
impl Default for QueuedBuf {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buf: Default::default(),
|
||||
displayed: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl QueuedBuf {
|
||||
fn update(&mut self, new: Vec<[u8; 4]>) {
|
||||
self.buf = new;
|
||||
|
@ -336,7 +345,7 @@ where
|
|||
scaled_height: inner_size.height / real_factor,
|
||||
};
|
||||
|
||||
let renderer = RendererBackend::new(resolutions, &window, shader_path, manager);
|
||||
let renderer = RendererBackend::new(resolutions, &window, shader_path, manager).unwrap();
|
||||
|
||||
let recording = if record {
|
||||
let configs = access_config();
|
||||
|
@ -374,19 +383,23 @@ where
|
|||
fn render(&mut self, manager: &Backend::RendererBackendManager) {
|
||||
let inner_size = self.window.inner_size();
|
||||
if !self.queued_buf.displayed {
|
||||
self.renderer.new_frame(&self.queued_buf.buf);
|
||||
self.renderer
|
||||
.new_frame(&self.queued_buf.buf)
|
||||
.some_or_print();
|
||||
self.queued_buf.displayed = true;
|
||||
}
|
||||
|
||||
self.renderer.render(
|
||||
ResolutionData {
|
||||
real_width: inner_size.width,
|
||||
real_height: inner_size.height,
|
||||
scaled_width: self.width as u32,
|
||||
scaled_height: self.height as u32,
|
||||
},
|
||||
manager,
|
||||
);
|
||||
self.renderer
|
||||
.render(
|
||||
ResolutionData {
|
||||
real_width: inner_size.width,
|
||||
real_height: inner_size.height,
|
||||
scaled_width: self.width as u32,
|
||||
scaled_height: self.height as u32,
|
||||
},
|
||||
manager,
|
||||
)
|
||||
.some_or_print();
|
||||
}
|
||||
|
||||
fn process(&mut self) {
|
||||
|
@ -426,7 +439,9 @@ where
|
|||
scaled_height: self.height as u32,
|
||||
};
|
||||
|
||||
self.renderer.resize(resolutions, &self.window);
|
||||
self.renderer
|
||||
.resize(resolutions, &self.window)
|
||||
.some_or_print();
|
||||
|
||||
self.window.request_redraw();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["plugin", "wgpu", "pixels", "vulkan-static"]
|
||||
default = ["plugin", "wgpu"]
|
||||
pixels = ["gb-emu-lib/pixels-renderer"]
|
||||
vulkan = ["gb-emu-lib/vulkan-renderer"]
|
||||
vulkan-static = ["vulkan", "gb-emu-lib/vulkan-static"]
|
||||
|
@ -32,4 +32,3 @@ futures = { version = "0.3", optional = true }
|
|||
keyboard-types = { version = "0.6.2", optional = true }
|
||||
raw-window-handle = { workspace = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
|
|
@ -6,6 +6,7 @@ use baseview::{
|
|||
use gb_emu_lib::{
|
||||
connect::{JoypadButtons, JoypadState, RendererMessage, ResolutionData, HEIGHT, WIDTH},
|
||||
renderer::{ActiveBackend, RendererBackend, RendererBackendManager},
|
||||
util::PrintErrors,
|
||||
};
|
||||
use keyboard_types::{Code, KeyState};
|
||||
use nih_plug::prelude::*;
|
||||
|
@ -135,7 +136,7 @@ impl TwincEditorWindow {
|
|||
};
|
||||
|
||||
let renderer =
|
||||
RendererBackend::new(current_resolution, window, shader_path, manager.clone());
|
||||
RendererBackend::new(current_resolution, window, shader_path, manager.clone()).unwrap();
|
||||
|
||||
Self {
|
||||
renderer,
|
||||
|
@ -178,10 +179,12 @@ impl WindowHandler for TwincEditorWindow {
|
|||
== (self.current_resolution.scaled_height * self.current_resolution.scaled_width)
|
||||
as usize
|
||||
{
|
||||
self.renderer.new_frame(&self.latest_buf);
|
||||
self.renderer.new_frame(&self.latest_buf).some_or_print();
|
||||
}
|
||||
|
||||
self.renderer.render(self.current_resolution, &self.manager);
|
||||
self.renderer
|
||||
.render(self.current_resolution, &self.manager)
|
||||
.some_or_print();
|
||||
}
|
||||
|
||||
fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus {
|
||||
|
@ -194,7 +197,9 @@ impl WindowHandler for TwincEditorWindow {
|
|||
scaled_width: WIDTH as u32,
|
||||
scaled_height: HEIGHT as u32,
|
||||
};
|
||||
self.renderer.resize(self.current_resolution, window);
|
||||
self.renderer
|
||||
.resize(self.current_resolution, window)
|
||||
.some_or_print();
|
||||
EventStatus::Captured
|
||||
}
|
||||
Event::Keyboard(event) => {
|
||||
|
|
|
@ -24,6 +24,7 @@ use frontend_common::{
|
|||
use gb_emu_lib::{
|
||||
connect::{EmulatorMessage, JoypadButtons, JoypadState, RendererMessage, ResolutionData},
|
||||
renderer::{ActiveBackend, RendererBackend, RendererBackendManager},
|
||||
util::PrintErrors,
|
||||
};
|
||||
use objc::{
|
||||
class, msg_send, msg_send_id,
|
||||
|
@ -141,9 +142,10 @@ const ALL_BUTTONS: [JoypadButtons; 8] = [
|
|||
|
||||
fn get_buttons(event: &Event) -> Option<JoypadButtons> {
|
||||
let characters = event.characters();
|
||||
if characters.len() != 1 {
|
||||
panic!("ok that assumption was wrong lol. event characters CAN be != 1");
|
||||
}
|
||||
// i have no idea why i left this check in? what was i looking for?
|
||||
// if characters.len() != 1 {
|
||||
// panic!("ok that assumption was wrong lol. event characters CAN be != 1");
|
||||
// }
|
||||
|
||||
if event.current_modifier_flags().is_empty() {
|
||||
for button in ALL_BUTTONS {
|
||||
|
@ -478,8 +480,10 @@ impl CacaoWindow {
|
|||
|
||||
fn display(&mut self, buffer: Vec<[u8; 4]>) {
|
||||
if let Some(backend) = self.backend.as_mut() {
|
||||
backend.render(self.resolutions, &self.backend_manager);
|
||||
backend.new_frame(&buffer);
|
||||
backend
|
||||
.render(self.resolutions, &self.backend_manager)
|
||||
.some_or_print();
|
||||
backend.new_frame(&buffer).some_or_print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -488,12 +492,13 @@ impl WindowDelegate for CacaoWindow {
|
|||
const NAME: &'static str = "EmulatorWindow";
|
||||
|
||||
fn did_load(&mut self, window: Window) {
|
||||
self.backend = Some(RendererBackend::new(
|
||||
self.backend = RendererBackend::new(
|
||||
self.resolutions,
|
||||
&WindowHandleWrapper(&window),
|
||||
self.shader_path.clone(),
|
||||
self.backend_manager.clone(),
|
||||
));
|
||||
)
|
||||
.some_or_print();
|
||||
}
|
||||
|
||||
fn will_close(&self) {
|
||||
|
|
|
@ -6,14 +6,17 @@ edition = "2021"
|
|||
[features]
|
||||
default = []
|
||||
clocked-serial = []
|
||||
vulkan-renderer = [
|
||||
"renderer",
|
||||
"dep:ash",
|
||||
"dep:ash-window",
|
||||
"dep:naga",
|
||||
librashader = [
|
||||
"dep:librashader",
|
||||
"dep:librashader-presets",
|
||||
"dep:librashader-common",
|
||||
]
|
||||
vulkan-renderer = [
|
||||
"renderer",
|
||||
"librashader",
|
||||
"dep:ash",
|
||||
"dep:ash-window",
|
||||
"dep:naga",
|
||||
"librashader/runtime-vk",
|
||||
]
|
||||
vulkan-static = ["dep:ash-molten", "vulkan-renderer"]
|
||||
|
@ -21,7 +24,7 @@ vulkan-debug = []
|
|||
pixels-renderer = ["renderer", "dep:pixels"]
|
||||
wgpu-renderer = [
|
||||
"renderer",
|
||||
"dep:librashader",
|
||||
"librashader",
|
||||
"librashader/runtime-wgpu",
|
||||
"dep:wgpu",
|
||||
]
|
||||
|
@ -41,7 +44,6 @@ num-traits = "0.2"
|
|||
pixels = { git = "https://git.alexjanka.com/alex/pixels", optional = true }
|
||||
ash = { workspace = true, features = ["linked"], optional = true }
|
||||
ash-window = { workspace = true, optional = true }
|
||||
|
||||
raw-window-handle = { workspace = true }
|
||||
librashader = { workspace = true, optional = true }
|
||||
librashader-presets = { workspace = true, optional = true }
|
||||
|
@ -50,6 +52,7 @@ directories = { version = "5.0", optional = true }
|
|||
ron = { version = "0.8", optional = true }
|
||||
lazy_static = "1.4"
|
||||
wgpu = { version = "0.19", optional = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
naga = { version = "0.19", optional = true, features = ["wgsl-in", "spv-out"] }
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
||||
|
||||
pub struct DummyHandle<'a> {
|
||||
pub window: raw_window_handle::WindowHandle<'a>,
|
||||
pub display: raw_window_handle::DisplayHandle<'a>,
|
||||
}
|
||||
|
||||
impl<'a> DummyHandle<'a> {
|
||||
pub fn new<T>(value: &'a T) -> Option<Self>
|
||||
where
|
||||
T: HasWindowHandle + HasDisplayHandle + 'a,
|
||||
{
|
||||
Some(Self {
|
||||
window: value.window_handle().ok()?,
|
||||
display: value.display_handle().ok()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for DummyHandle<'a> {}
|
||||
unsafe impl<'a> Send for DummyHandle<'a> {}
|
||||
|
||||
impl<'a> HasWindowHandle for DummyHandle<'a> {
|
||||
fn window_handle(
|
||||
&self,
|
||||
) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
|
||||
Ok(self.window)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HasDisplayHandle for DummyHandle<'a> {
|
||||
fn display_handle(&self) -> Result<DisplayHandle<'_>, raw_window_handle::HandleError> {
|
||||
Ok(self.display)
|
||||
}
|
||||
}
|
|
@ -21,24 +21,32 @@ pub mod vulkan;
|
|||
#[cfg(feature = "wgpu-renderer")]
|
||||
pub mod wgpu;
|
||||
|
||||
mod compat;
|
||||
#[cfg(feature = "librashader")]
|
||||
mod shaders;
|
||||
|
||||
pub trait RendererBackend {
|
||||
type RendererBackendManager: RendererBackendManager;
|
||||
type RendererError: std::error::Error;
|
||||
|
||||
fn new<W: HasDisplayHandle + HasWindowHandle>(
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
shader_path: Option<PathBuf>,
|
||||
manager: Arc<Self::RendererBackendManager>,
|
||||
) -> Self;
|
||||
) -> Result<Self, Self::RendererError>
|
||||
where
|
||||
Self: std::marker::Sized;
|
||||
fn resize<W: HasDisplayHandle + HasWindowHandle>(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
);
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]);
|
||||
fn render(&mut self, resolutions: ResolutionData, manager: &Self::RendererBackendManager);
|
||||
) -> Result<(), Self::RendererError>;
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) -> Result<(), Self::RendererError>;
|
||||
fn render(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
manager: &Self::RendererBackendManager,
|
||||
) -> Result<(), Self::RendererError>;
|
||||
}
|
||||
|
||||
pub trait RendererBackendManager {
|
||||
|
|
|
@ -2,10 +2,11 @@ use std::{path::PathBuf, sync::Arc};
|
|||
|
||||
use pixels::{Pixels, SurfaceTexture};
|
||||
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::connect::ResolutionData;
|
||||
|
||||
use super::{compat::DummyHandle, RendererBackend, RendererBackendManager};
|
||||
use super::{RendererBackend, RendererBackendManager};
|
||||
|
||||
pub struct PixelsBackendManager {}
|
||||
|
||||
|
@ -21,43 +22,51 @@ pub struct PixelsBackend {
|
|||
|
||||
impl RendererBackend for PixelsBackend {
|
||||
type RendererBackendManager = PixelsBackendManager;
|
||||
type RendererError = PixelsError;
|
||||
|
||||
fn new<W: HasDisplayHandle + HasWindowHandle>(
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
_: Option<PathBuf>,
|
||||
_: Arc<Self::RendererBackendManager>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pixels: new_pixels(resolutions, window),
|
||||
}
|
||||
) -> Result<Self, Self::RendererError> {
|
||||
Ok(Self {
|
||||
pixels: new_pixels(resolutions, window)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn resize<W: HasDisplayHandle + HasWindowHandle>(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
) {
|
||||
self.pixels = new_pixels(resolutions, window);
|
||||
) -> Result<(), Self::RendererError> {
|
||||
self.pixels = new_pixels(resolutions, window)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) {
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) -> Result<(), Self::RendererError> {
|
||||
if !buffer.is_empty() {
|
||||
self.pixels
|
||||
.frame_mut()
|
||||
.copy_from_slice(bytemuck::cast_slice(buffer));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render(&mut self, _: ResolutionData, _: &PixelsBackendManager) {
|
||||
self.pixels.render().unwrap();
|
||||
fn render(
|
||||
&mut self,
|
||||
_: ResolutionData,
|
||||
_: &PixelsBackendManager,
|
||||
) -> Result<(), Self::RendererError> {
|
||||
self.pixels.render()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn new_pixels<W: HasDisplayHandle + HasWindowHandle>(
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
) -> Pixels {
|
||||
) -> Result<Pixels, pixels::Error> {
|
||||
let dummy = DummyHandle::new(window).unwrap();
|
||||
let surface_texture: SurfaceTexture<'_, DummyHandle> =
|
||||
SurfaceTexture::new(resolutions.real_width, resolutions.real_height, &dummy);
|
||||
|
@ -71,5 +80,44 @@ fn new_pixels<W: HasDisplayHandle + HasWindowHandle>(
|
|||
..pixels::wgpu::RequestAdapterOptionsBase::default()
|
||||
})
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PixelsError {
|
||||
#[error("pixels error")]
|
||||
Pixels(#[from] pixels::Error),
|
||||
}
|
||||
|
||||
struct DummyHandle<'a> {
|
||||
window: raw_window_handle::WindowHandle<'a>,
|
||||
display: raw_window_handle::DisplayHandle<'a>,
|
||||
}
|
||||
|
||||
impl<'a> DummyHandle<'a> {
|
||||
fn new<T>(value: &'a T) -> Option<Self>
|
||||
where
|
||||
T: HasWindowHandle + HasDisplayHandle + 'a,
|
||||
{
|
||||
Some(Self {
|
||||
window: value.window_handle().ok()?,
|
||||
display: value.display_handle().ok()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for DummyHandle<'a> {}
|
||||
unsafe impl<'a> Send for DummyHandle<'a> {}
|
||||
|
||||
impl<'a> HasWindowHandle for DummyHandle<'a> {
|
||||
fn window_handle(
|
||||
&self,
|
||||
) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
|
||||
Ok(self.window)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HasDisplayHandle for DummyHandle<'a> {
|
||||
fn display_handle(&self) -> Result<DisplayHandle<'_>, raw_window_handle::HandleError> {
|
||||
Ok(self.display)
|
||||
}
|
||||
}
|
||||
|
|
33
lib/src/renderer/shaders/mod.rs
Normal file
33
lib/src/renderer/shaders/mod.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use librashader_presets::ShaderPreset;
|
||||
|
||||
pub fn default_preset() -> ShaderPreset {
|
||||
ShaderPreset {
|
||||
shader_count: 1,
|
||||
shaders: vec![librashader_presets::ShaderPassConfig {
|
||||
id: 0,
|
||||
name: librashader_common::ShaderStorage::String(
|
||||
include_str!("./stock.slang").to_string(),
|
||||
),
|
||||
alias: None,
|
||||
filter: librashader::FilterMode::Nearest,
|
||||
wrap_mode: librashader::WrapMode::ClampToBorder,
|
||||
frame_count_mod: 0,
|
||||
srgb_framebuffer: false,
|
||||
float_framebuffer: false,
|
||||
mipmap_input: false,
|
||||
scaling: librashader_presets::Scale2D {
|
||||
valid: false,
|
||||
x: librashader_presets::Scaling {
|
||||
scale_type: librashader_presets::ScaleType::Input,
|
||||
factor: librashader_presets::ScaleFactor::Float(1.0),
|
||||
},
|
||||
y: librashader_presets::Scaling {
|
||||
scale_type: librashader_presets::ScaleType::Input,
|
||||
factor: librashader_presets::ScaleFactor::Float(1.0),
|
||||
},
|
||||
},
|
||||
}],
|
||||
textures: vec![],
|
||||
parameters: vec![],
|
||||
}
|
||||
}
|
|
@ -7,14 +7,17 @@ use std::{mem::ManuallyDrop, path::PathBuf, sync::Arc};
|
|||
use crate::connect::ResolutionData;
|
||||
|
||||
use self::{
|
||||
types::{FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData, SHADER_INPUT_FORMAT},
|
||||
types::{
|
||||
FramebufferData, SurfaceData, SwapchainData, Vertex, VulkanData, VulkanError,
|
||||
SHADER_INPUT_FORMAT,
|
||||
},
|
||||
utils::{
|
||||
begin_commandbuffer, find_memorytype_index, record_submit_commandbuffer,
|
||||
submit_commandbuffer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{RendererBackend, RendererBackendManager};
|
||||
use super::{shaders::default_preset, RendererBackend, RendererBackendManager};
|
||||
|
||||
#[cfg(all(debug_assertions, feature = "vulkan-debug"))]
|
||||
mod debug;
|
||||
|
@ -119,14 +122,15 @@ pub struct VulkanWindowOptions {
|
|||
|
||||
impl RendererBackend for VulkanBackend {
|
||||
type RendererBackendManager = VulkanBackendManager;
|
||||
type RendererError = VulkanError;
|
||||
|
||||
fn new<W: HasDisplayHandle + HasWindowHandle>(
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
shader_path: Option<PathBuf>,
|
||||
manager: Arc<VulkanBackendManager>,
|
||||
) -> Self {
|
||||
let inner = unsafe { VulkanWindowInner::new(resolutions, window, manager.as_ref()) };
|
||||
) -> Result<Self, Self::RendererError> {
|
||||
let inner = unsafe { VulkanWindowInner::new(resolutions, &window, manager.as_ref()) };
|
||||
|
||||
let filter_chain_options = FilterChainOptions {
|
||||
frames_in_flight: 0,
|
||||
|
@ -148,64 +152,44 @@ impl RendererBackend for VulkanBackend {
|
|||
.unwrap()
|
||||
}
|
||||
None => unsafe {
|
||||
let preset = librashader_presets::ShaderPreset {
|
||||
shader_count: 1,
|
||||
shaders: vec![librashader_presets::ShaderPassConfig {
|
||||
id: 0,
|
||||
name: librashader_common::ShaderStorage::String(
|
||||
include_str!("./shaders/stock.slang").to_string(),
|
||||
),
|
||||
alias: None,
|
||||
filter: librashader::FilterMode::Nearest,
|
||||
wrap_mode: librashader::WrapMode::ClampToBorder,
|
||||
frame_count_mod: 0,
|
||||
srgb_framebuffer: false,
|
||||
float_framebuffer: false,
|
||||
mipmap_input: false,
|
||||
scaling: librashader_presets::Scale2D {
|
||||
valid: false,
|
||||
x: librashader_presets::Scaling {
|
||||
scale_type: librashader_presets::ScaleType::Input,
|
||||
factor: librashader_presets::ScaleFactor::Float(1.0),
|
||||
},
|
||||
y: librashader_presets::Scaling {
|
||||
scale_type: librashader_presets::ScaleType::Input,
|
||||
factor: librashader_presets::ScaleFactor::Float(1.0),
|
||||
},
|
||||
},
|
||||
}],
|
||||
textures: vec![],
|
||||
parameters: vec![],
|
||||
};
|
||||
FilterChain::load_from_preset(preset, vulkan, Some(&filter_chain_options))
|
||||
FilterChain::load_from_preset(default_preset(), vulkan, Some(&filter_chain_options))
|
||||
}
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
Self {
|
||||
// TODO - don't unwrap
|
||||
Ok(Self {
|
||||
inner: ManuallyDrop::new(inner),
|
||||
filter_chain: ManuallyDrop::new(filter_chain),
|
||||
manager,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn resize<W: HasDisplayHandle + HasWindowHandle>(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
_window: &W,
|
||||
) {
|
||||
) -> Result<(), Self::RendererError> {
|
||||
unsafe { self.inner.resize(resolutions, self.manager.as_ref()) };
|
||||
// TODO - make inner return a result
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) {
|
||||
unsafe { self.inner.new_frame(buffer) };
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) -> Result<(), Self::RendererError> {
|
||||
unsafe { self.inner.new_frame(buffer) }; // TODO - make inner return a result
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render(&mut self, resolutions: ResolutionData, manager: &VulkanBackendManager) {
|
||||
fn render(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
manager: &VulkanBackendManager,
|
||||
) -> Result<(), Self::RendererError> {
|
||||
unsafe {
|
||||
self.inner
|
||||
.render(&mut self.filter_chain, resolutions, manager)
|
||||
};
|
||||
}; // TODO - make inner return a result
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use ash::{
|
|||
};
|
||||
#[allow(deprecated)]
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::connect::ResolutionData;
|
||||
|
||||
|
@ -12,6 +13,12 @@ use super::{
|
|||
VulkanBackendManager,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum VulkanError {
|
||||
#[error("vulkan error")]
|
||||
Vulkan, //(#[from] vk::Error),
|
||||
}
|
||||
|
||||
pub(super) const SHADER_INPUT_FORMAT: vk::Format = vk::Format::R8G8B8A8_UNORM;
|
||||
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
|
|
|
@ -1,45 +1,274 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use futures::executor::block_on;
|
||||
use librashader::runtime::wgpu::{FilterChain, FilterChainOptions};
|
||||
use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
|
||||
use thiserror::Error;
|
||||
use wgpu::{Device, Queue, Surface, SurfaceConfiguration};
|
||||
|
||||
use crate::{
|
||||
connect::ResolutionData,
|
||||
renderer::{RendererBackend, RendererBackendManager},
|
||||
};
|
||||
|
||||
pub struct WgpuBackend {}
|
||||
use super::shaders::default_preset;
|
||||
|
||||
const SHADER_INPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm;
|
||||
|
||||
pub struct WgpuBackendManager {
|
||||
instance: wgpu::Instance,
|
||||
}
|
||||
|
||||
impl RendererBackendManager for WgpuBackendManager {
|
||||
fn new(_display_handle: DisplayHandle) -> Self {
|
||||
let instance = wgpu::Instance::default();
|
||||
Self { instance }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuBackend {
|
||||
device: Arc<Device>,
|
||||
queue: Arc<Queue>,
|
||||
surface: Surface<'static>,
|
||||
resolutions: ResolutionData,
|
||||
format: wgpu::TextureFormat,
|
||||
alpha_mode: wgpu::CompositeAlphaMode,
|
||||
filter_chain: FilterChain,
|
||||
gb_framebuffer: Arc<wgpu::Texture>,
|
||||
frame_num: usize,
|
||||
}
|
||||
|
||||
impl ResolutionData {
|
||||
fn get_config(
|
||||
&self,
|
||||
format: wgpu::TextureFormat,
|
||||
alpha_mode: wgpu::CompositeAlphaMode,
|
||||
) -> SurfaceConfiguration {
|
||||
wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST,
|
||||
format,
|
||||
width: self.real_width,
|
||||
height: self.real_height,
|
||||
present_mode: wgpu::PresentMode::Fifo,
|
||||
desired_maximum_frame_latency: 2,
|
||||
alpha_mode,
|
||||
view_formats: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn scaled_as_extent(&self) -> wgpu::Extent3d {
|
||||
wgpu::Extent3d {
|
||||
width: self.scaled_width,
|
||||
height: self.scaled_height,
|
||||
depth_or_array_layers: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RendererBackend for WgpuBackend {
|
||||
type RendererBackendManager = WgpuBackendManager;
|
||||
type RendererError = WgpuError;
|
||||
|
||||
fn new<W: HasDisplayHandle + HasWindowHandle>(
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
shader_path: Option<std::path::PathBuf>,
|
||||
manager: std::sync::Arc<Self::RendererBackendManager>,
|
||||
) -> Self {
|
||||
todo!()
|
||||
) -> Result<Self, Self::RendererError> {
|
||||
let surface = unsafe {
|
||||
manager
|
||||
.instance
|
||||
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(window)?)
|
||||
}?;
|
||||
|
||||
let adapter = manager
|
||||
.instance
|
||||
.enumerate_adapters(wgpu::Backends::all())
|
||||
.into_iter()
|
||||
.find(|adapter| adapter.is_surface_supported(&surface))
|
||||
.ok_or(Self::RendererError::NoAdapter)?;
|
||||
let (device, queue) = block_on(adapter.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
required_features: wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
required_limits: wgpu::Limits::default(),
|
||||
label: None,
|
||||
},
|
||||
None,
|
||||
))?;
|
||||
let (device, queue) = (Arc::new(device), Arc::new(queue));
|
||||
let capabilities = surface.get_capabilities(&adapter);
|
||||
let format = capabilities
|
||||
.formats
|
||||
.into_iter()
|
||||
.find(|v| !v.is_srgb())
|
||||
.ok_or(Self::RendererError::NoTextureFormat)?;
|
||||
let alpha_mode = *capabilities
|
||||
.alpha_modes
|
||||
.first()
|
||||
.ok_or(Self::RendererError::NoTextureFormat)?;
|
||||
|
||||
let filter_chain = {
|
||||
let filter_chain_options = FilterChainOptions {
|
||||
force_no_mipmaps: false,
|
||||
};
|
||||
match shader_path {
|
||||
Some(path) => FilterChain::load_from_path(
|
||||
path,
|
||||
device.clone(),
|
||||
queue.clone(),
|
||||
Some(&filter_chain_options),
|
||||
)
|
||||
.unwrap(), //?,
|
||||
None => {
|
||||
FilterChain::load_from_preset(
|
||||
default_preset(),
|
||||
device.clone(),
|
||||
queue.clone(),
|
||||
Some(&filter_chain_options),
|
||||
)
|
||||
}?,
|
||||
}
|
||||
};
|
||||
|
||||
let gb_framebuffer = Arc::new(device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("rendertexture"),
|
||||
size: resolutions.scaled_as_extent(),
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: SHADER_INPUT_FORMAT,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[SHADER_INPUT_FORMAT],
|
||||
}));
|
||||
|
||||
Ok(Self {
|
||||
device,
|
||||
queue,
|
||||
surface,
|
||||
resolutions,
|
||||
format,
|
||||
alpha_mode,
|
||||
filter_chain,
|
||||
gb_framebuffer,
|
||||
frame_num: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn resize<W: HasDisplayHandle + HasWindowHandle>(
|
||||
&mut self,
|
||||
resolutions: ResolutionData,
|
||||
window: &W,
|
||||
) {
|
||||
todo!()
|
||||
_window: &W,
|
||||
) -> Result<(), Self::RendererError> {
|
||||
self.resolutions = resolutions;
|
||||
self.surface.configure(
|
||||
&self.device,
|
||||
&self.resolutions.get_config(self.format, self.alpha_mode),
|
||||
);
|
||||
self.gb_framebuffer = Arc::new(self.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("rendertexture"),
|
||||
size: resolutions.scaled_as_extent(),
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: SHADER_INPUT_FORMAT,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[SHADER_INPUT_FORMAT],
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) {
|
||||
todo!()
|
||||
fn new_frame(&mut self, buffer: &[[u8; 4]]) -> Result<(), Self::RendererError> {
|
||||
self.queue.write_texture(
|
||||
self.gb_framebuffer.as_image_copy(),
|
||||
bytemuck::cast_slice(buffer),
|
||||
wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(self.resolutions.scaled_width * 4),
|
||||
rows_per_image: None,
|
||||
},
|
||||
self.resolutions.scaled_as_extent(),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render(&mut self, resolutions: ResolutionData, manager: &Self::RendererBackendManager) {
|
||||
todo!()
|
||||
fn render(
|
||||
&mut self,
|
||||
_resolutions: ResolutionData,
|
||||
_manager: &Self::RendererBackendManager,
|
||||
) -> Result<(), Self::RendererError> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
|
||||
let filter_output = Arc::new(self.device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("filteroutput"),
|
||||
size: output.texture.size(),
|
||||
mip_level_count: output.texture.mip_level_count(),
|
||||
sample_count: output.texture.sample_count(),
|
||||
dimension: output.texture.dimension(),
|
||||
format: output.texture.format(),
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING
|
||||
| wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||
| wgpu::TextureUsages::COPY_DST
|
||||
| wgpu::TextureUsages::COPY_SRC,
|
||||
view_formats: &[output.texture.format()],
|
||||
}));
|
||||
|
||||
let filter_view = filter_output.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||
|
||||
self.filter_chain.frame(
|
||||
self.gb_framebuffer.clone(),
|
||||
&librashader_common::Viewport {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
mvp: None,
|
||||
output: librashader::runtime::wgpu::WgpuOutputView::new_from_raw(
|
||||
&filter_view,
|
||||
filter_output.size().into(),
|
||||
filter_output.format(),
|
||||
),
|
||||
},
|
||||
&mut encoder,
|
||||
self.frame_num,
|
||||
None,
|
||||
)?;
|
||||
|
||||
encoder.copy_texture_to_texture(
|
||||
filter_output.as_image_copy(),
|
||||
output.texture.as_image_copy(),
|
||||
output.texture.size(),
|
||||
);
|
||||
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
self.frame_num += 1;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuBackendManager {}
|
||||
|
||||
impl RendererBackendManager for WgpuBackendManager {
|
||||
fn new(display_handle: DisplayHandle) -> Self {
|
||||
todo!()
|
||||
}
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WgpuError {
|
||||
#[error("no adapter")]
|
||||
NoAdapter,
|
||||
#[error("no texture format")]
|
||||
NoTextureFormat,
|
||||
#[error("rwh error")]
|
||||
RawWindowHandle(#[from] raw_window_handle::HandleError),
|
||||
#[error("create surface error")]
|
||||
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
||||
#[error("wgpu surface error")]
|
||||
Surface(#[from] wgpu::SurfaceError),
|
||||
#[error("request device error")]
|
||||
RequestDevice(#[from] wgpu::RequestDeviceError),
|
||||
#[error("librashader filterchain error")]
|
||||
FilterChain(#[from] librashader::runtime::wgpu::error::FilterChainError),
|
||||
}
|
||||
|
|
|
@ -3,6 +3,40 @@ use num_traits::{PrimInt, Unsigned};
|
|||
use crate::processor::{memory::mmio::gpu::Colour, Direction};
|
||||
use std::mem::transmute;
|
||||
|
||||
pub trait PrintErrors {
|
||||
type Inner;
|
||||
|
||||
fn some_or_print(self) -> Option<Self::Inner>;
|
||||
fn some_or_print_with_context(self, context: &str) -> Option<Self::Inner>;
|
||||
}
|
||||
|
||||
impl<T, E> PrintErrors for Result<T, E>
|
||||
where
|
||||
E: std::error::Error,
|
||||
{
|
||||
type Inner = T;
|
||||
|
||||
fn some_or_print(self) -> Option<Self::Inner> {
|
||||
match self {
|
||||
Ok(val) => Some(val),
|
||||
Err(e) => {
|
||||
eprintln!("{e:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn some_or_print_with_context(self, context: &str) -> Option<Self::Inner> {
|
||||
match self {
|
||||
Ok(val) => Some(val),
|
||||
Err(e) => {
|
||||
eprintln!("{context}: {e:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn as_signed(unsigned: u8) -> i8 {
|
||||
unsafe { transmute(unsigned) }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue