Cleanly separate the two texture dimensions
- The pixel buffer dimensions - The surface texture dimensions
This commit is contained in:
parent
44f5b67c9e
commit
2ec43fccd1
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -683,12 +683,19 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"raw-window-handle 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pixels-mocks 0.1.0",
|
||||||
"vk-shader-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vk-shader-macros 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wgpu 0.3.0 (git+https://github.com/gfx-rs/wgpu-rs?rev=697393df4793e1a58578209885036114adfb9213)",
|
"wgpu 0.3.0 (git+https://github.com/gfx-rs/wgpu-rs?rev=697393df4793e1a58578209885036114adfb9213)",
|
||||||
"winit 0.20.0-alpha3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winit 0.20.0-alpha3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pixels-mocks"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"raw-window-handle 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.16"
|
version = "0.3.16"
|
||||||
|
|
|
@ -17,5 +17,10 @@ wgpu = { git = "https://github.com/gfx-rs/wgpu-rs", rev = "697393df4793e1a585782
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.7"
|
env_logger = "0.7"
|
||||||
log = { version = "0.4", features = ["release_max_level_warn"] }
|
log = { version = "0.4", features = ["release_max_level_warn"] }
|
||||||
raw-window-handle = "0.1"
|
pixels-mocks = { path = "pixels-mocks" }
|
||||||
winit = "0.20.0-alpha3"
|
winit = "0.20.0-alpha3"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"pixels-mocks",
|
||||||
|
]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use pixels::{Error, Pixels};
|
use pixels::{Error, Pixels, SurfaceTexture};
|
||||||
use winit::event;
|
use winit::event;
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
|
||||||
|
@ -6,14 +6,16 @@ fn main() -> Result<(), Error> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
|
|
||||||
let (window, surface) = {
|
let (window, surface, width, height) = {
|
||||||
let window = winit::window::Window::new(&event_loop).unwrap();
|
let window = winit::window::Window::new(&event_loop).unwrap();
|
||||||
let surface = wgpu::Surface::create(&window);
|
let surface = wgpu::Surface::create(&window);
|
||||||
|
let size = window.inner_size().to_physical(window.hidpi_factor());
|
||||||
|
|
||||||
(window, surface)
|
(window, surface, size.width as u32, size.height as u32)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut fb = Pixels::new(320, 240, &surface)?;
|
let surface_texture = SurfaceTexture::new(width, height, &surface);
|
||||||
|
let mut fb = Pixels::new(320, 240, surface_texture)?;
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| match event {
|
event_loop.run(move |event, _, control_flow| match event {
|
||||||
event::Event::WindowEvent { event, .. } => match event {
|
event::Event::WindowEvent { event, .. } => match event {
|
||||||
|
|
9
pixels-mocks/Cargo.toml
Normal file
9
pixels-mocks/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "pixels-mocks"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Jay Oster <jay@kodewerx.org>"]
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
raw-window-handle = "0.1"
|
24
pixels-mocks/src/lib.rs
Normal file
24
pixels-mocks/src/lib.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
pub struct RWH;
|
||||||
|
|
||||||
|
unsafe impl raw_window_handle::HasRawWindowHandle for RWH {
|
||||||
|
fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
return raw_window_handle::RawWindowHandle::MacOS(
|
||||||
|
raw_window_handle::macos::MacOSHandle::empty(),
|
||||||
|
);
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "linux",
|
||||||
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
))]
|
||||||
|
return raw_window_handle::RawWindowHandle::X11(raw_window_handle::unix::X11Handle::empty());
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return raw_window_handle::RawWindowHandle::Windows(
|
||||||
|
raw_window_handle::windows::WindowsHandle::empty(),
|
||||||
|
);
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
|
return raw_window_handle::RawWindowHandle::IOS(raw_window_handle::ios::IOSHandle::empty());
|
||||||
|
}
|
||||||
|
}
|
171
src/lib.rs
171
src/lib.rs
|
@ -17,6 +17,14 @@ use std::fmt;
|
||||||
use vk_shader_macros::include_glsl;
|
use vk_shader_macros::include_glsl;
|
||||||
pub use wgpu;
|
pub use wgpu;
|
||||||
|
|
||||||
|
/// A logical texture for a window surface.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SurfaceTexture<'a> {
|
||||||
|
surface: &'a wgpu::Surface,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a 2D frame buffer with an explicit image resolution.
|
/// Represents a 2D frame buffer with an explicit image resolution.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Pixels {
|
pub struct Pixels {
|
||||||
|
@ -32,6 +40,8 @@ pub struct Pixels {
|
||||||
pub struct PixelsOptions {
|
pub struct PixelsOptions {
|
||||||
request_adapter_options: wgpu::RequestAdapterOptions,
|
request_adapter_options: wgpu::RequestAdapterOptions,
|
||||||
device_descriptor: wgpu::DeviceDescriptor,
|
device_descriptor: wgpu::DeviceDescriptor,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All the ways in which creating a frame buffer can fail.
|
/// All the ways in which creating a frame buffer can fail.
|
||||||
|
@ -41,38 +51,55 @@ pub enum Error {
|
||||||
AdapterNotFound,
|
AdapterNotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> SurfaceTexture<'a> {
|
||||||
|
/// Create a logical texture for a window surface.
|
||||||
|
///
|
||||||
|
/// It is recommended (but not required) that the `width` and `height` are
|
||||||
|
/// equivalent to the physical dimentions of the `surface`. E.g. scaled by
|
||||||
|
/// the HiDPI factor.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use pixels::SurfaceTexture;
|
||||||
|
/// use wgpu::Surface;
|
||||||
|
/// use winit::event_loop::EventLoop;
|
||||||
|
/// use winit::window::Window;
|
||||||
|
///
|
||||||
|
/// let event_loop = EventLoop::new();
|
||||||
|
/// let window = Window::new(&event_loop).unwrap();
|
||||||
|
/// let surface = Surface::create(&window);
|
||||||
|
/// let size = window.inner_size().to_physical(window.hidpi_factor());
|
||||||
|
///
|
||||||
|
/// let width = size.width as u32;
|
||||||
|
/// let height = size.height as u32;
|
||||||
|
///
|
||||||
|
/// let surface_texture = SurfaceTexture::new(width, height, &surface);
|
||||||
|
/// # Ok::<(), pixels::Error>(())
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics when `width` or `height` are 0.
|
||||||
|
pub fn new(width: u32, height: u32, surface: &'a wgpu::Surface) -> SurfaceTexture<'a> {
|
||||||
|
assert!(width > 0);
|
||||||
|
assert!(height > 0);
|
||||||
|
|
||||||
|
SurfaceTexture {
|
||||||
|
surface,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use pixels::Pixels;
|
/// # use pixels::Pixels;
|
||||||
/// # struct RWH();
|
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
|
||||||
/// # unsafe impl raw_window_handle::HasRawWindowHandle for RWH {
|
/// # let surface_texture = pixels::SurfaceTexture::new(1024, 768, &surface);
|
||||||
/// # fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
|
/// let fb = Pixels::new(320, 240, surface_texture)?;
|
||||||
/// # #[cfg(target_os = "macos")]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::MacOS(
|
|
||||||
/// # raw_window_handle::macos::MacOSHandle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # #[cfg(any(
|
|
||||||
/// # target_os = "linux",
|
|
||||||
/// # target_os = "dragonfly",
|
|
||||||
/// # target_os = "freebsd",
|
|
||||||
/// # target_os = "netbsd",
|
|
||||||
/// # target_os = "openbsd"))]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::X11(
|
|
||||||
/// # raw_window_handle::unix::X11Handle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # #[cfg(target_os = "windows")]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::Windows(
|
|
||||||
/// # raw_window_handle::windows::WindowsHandle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # #[cfg(target_os = "ios")]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::IOS(
|
|
||||||
/// # raw_window_handle::ios::IOSHandle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// # let surface = wgpu::Surface::create(&RWH());
|
|
||||||
/// let fb = Pixels::new(320, 240, &surface)?;
|
|
||||||
/// # Ok::<(), pixels::Error>(())
|
/// # Ok::<(), pixels::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
impl Pixels {
|
impl Pixels {
|
||||||
|
@ -81,8 +108,12 @@ impl Pixels {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns an error when a `wgpu::Adapter` cannot be found.
|
/// Returns an error when a `wgpu::Adapter` cannot be found.
|
||||||
pub fn new(width: u32, height: u32, surface: &wgpu::Surface) -> Result<Pixels, Error> {
|
///
|
||||||
Pixels::new_with_options(width, height, surface, PixelsOptions::new())
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics when `width` or `height` are 0.
|
||||||
|
pub fn new(width: u32, height: u32, surface_texture: SurfaceTexture) -> Result<Pixels, Error> {
|
||||||
|
Pixels::new_with_options(surface_texture, PixelsOptions::new(width, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a frame buffer instance with the given options.
|
/// Create a frame buffer instance with the given options.
|
||||||
|
@ -92,11 +123,11 @@ impl Pixels {
|
||||||
/// Returns an error when a `wgpu::Adapter` cannot be found or shaders
|
/// Returns an error when a `wgpu::Adapter` cannot be found or shaders
|
||||||
/// are invalid SPIR-V.
|
/// are invalid SPIR-V.
|
||||||
pub fn new_with_options(
|
pub fn new_with_options(
|
||||||
width: u32,
|
surface_texture: SurfaceTexture,
|
||||||
height: u32,
|
|
||||||
surface: &wgpu::Surface,
|
|
||||||
options: PixelsOptions,
|
options: PixelsOptions,
|
||||||
) -> Result<Pixels, Error> {
|
) -> Result<Pixels, Error> {
|
||||||
|
// TODO: Create a texture with the dimensions specified in `options`
|
||||||
|
|
||||||
let adapter = wgpu::Adapter::request(&options.request_adapter_options)
|
let adapter = wgpu::Adapter::request(&options.request_adapter_options)
|
||||||
.ok_or(Error::AdapterNotFound)?;
|
.ok_or(Error::AdapterNotFound)?;
|
||||||
let (device, queue) = adapter.request_device(&options.device_descriptor);
|
let (device, queue) = adapter.request_device(&options.device_descriptor);
|
||||||
|
@ -148,12 +179,12 @@ impl Pixels {
|
||||||
});
|
});
|
||||||
|
|
||||||
let swap_chain = device.create_swap_chain(
|
let swap_chain = device.create_swap_chain(
|
||||||
&surface,
|
surface_texture.surface,
|
||||||
&wgpu::SwapChainDescriptor {
|
&wgpu::SwapChainDescriptor {
|
||||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
width,
|
width: surface_texture.width,
|
||||||
height,
|
height: surface_texture.height,
|
||||||
present_mode: wgpu::PresentMode::Vsync,
|
present_mode: wgpu::PresentMode::Vsync,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -200,43 +231,30 @@ impl Pixels {
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use pixels::PixelsOptions;
|
/// # use pixels::PixelsOptions;
|
||||||
/// # struct RWH();
|
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
|
||||||
/// # unsafe impl raw_window_handle::HasRawWindowHandle for RWH {
|
/// # let surface_texture = pixels::SurfaceTexture::new(1024, 768, &surface);
|
||||||
/// # fn raw_window_handle(&self) -> raw_window_handle::RawWindowHandle {
|
/// let fb = PixelsOptions::new(320, 240)
|
||||||
/// # #[cfg(target_os = "macos")]
|
/// # // TODO: demonstrate adding a render pass here
|
||||||
/// # return raw_window_handle::RawWindowHandle::MacOS(
|
/// # //.render_pass(...)
|
||||||
/// # raw_window_handle::macos::MacOSHandle::empty()
|
/// .build(surface_texture)?;
|
||||||
/// # );
|
/// # Ok::<(), pixels::Error>(())
|
||||||
/// # #[cfg(any(
|
|
||||||
/// # target_os = "linux",
|
|
||||||
/// # target_os = "dragonfly",
|
|
||||||
/// # target_os = "freebsd",
|
|
||||||
/// # target_os = "netbsd",
|
|
||||||
/// # target_os = "openbsd"))]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::X11(
|
|
||||||
/// # raw_window_handle::unix::X11Handle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # #[cfg(target_os = "windows")]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::Windows(
|
|
||||||
/// # raw_window_handle::windows::WindowsHandle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # #[cfg(target_os = "ios")]
|
|
||||||
/// # return raw_window_handle::RawWindowHandle::IOS(
|
|
||||||
/// # raw_window_handle::ios::IOSHandle::empty()
|
|
||||||
/// # );
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// # fn main() -> Result<(), pixels::Error> {
|
|
||||||
/// # let surface = wgpu::Surface::create(&RWH());
|
|
||||||
/// let fb = PixelsOptions::new()
|
|
||||||
/// .build(320, 240, &surface)?;
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// ```
|
/// ```
|
||||||
impl PixelsOptions {
|
impl PixelsOptions {
|
||||||
/// Create a builder that can be finalized into a frame buffer instance.
|
/// Create a builder that can be finalized into a frame buffer instance.
|
||||||
pub fn new() -> PixelsOptions {
|
///
|
||||||
PixelsOptions::default()
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics when `width` or `height` are 0.
|
||||||
|
pub fn new(width: u32, height: u32) -> PixelsOptions {
|
||||||
|
assert!(width > 0);
|
||||||
|
assert!(height > 0);
|
||||||
|
|
||||||
|
PixelsOptions {
|
||||||
|
request_adapter_options: wgpu::RequestAdapterOptions::default(),
|
||||||
|
device_descriptor: wgpu::DeviceDescriptor::default(),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add options for requesting a `wgpu::Adapter`.
|
/// Add options for requesting a `wgpu::Adapter`.
|
||||||
|
@ -257,17 +275,8 @@ impl PixelsOptions {
|
||||||
///
|
///
|
||||||
/// Returns an error when a `wgpu::Adapter` cannot be found or shaders
|
/// Returns an error when a `wgpu::Adapter` cannot be found or shaders
|
||||||
/// are invalid SPIR-V.
|
/// are invalid SPIR-V.
|
||||||
pub fn build(self, width: u32, height: u32, surface: &wgpu::Surface) -> Result<Pixels, Error> {
|
pub fn build(self, surface_texture: SurfaceTexture) -> Result<Pixels, Error> {
|
||||||
Pixels::new_with_options(width, height, surface, self)
|
Pixels::new_with_options(surface_texture, self)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PixelsOptions {
|
|
||||||
fn default() -> PixelsOptions {
|
|
||||||
PixelsOptions {
|
|
||||||
request_adapter_options: wgpu::RequestAdapterOptions::default(),
|
|
||||||
device_descriptor: wgpu::DeviceDescriptor::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue