553: Add hello-windows example r=kvark a=qthree

# `hello-windows`
## Description

This is demonstration of ability to create multiple windows with differently colored backgrounds.

## Screenshot
![screenshot](https://user-images.githubusercontent.com/9898555/92568685-bc411c80-f2a9-11ea-9d4d-84bb236c40f9.png)

# `shared-textures` (old version)
## Description

This is demonstration of ability to create multiple windows and share single texture across all of them.
Available in ad3030ae8f61e3ea3f7b913cd03c366119d058fb commit.

## Screenshot
![screenshot](https://user-images.githubusercontent.com/9898555/92500037-cc63e800-f226-11ea-8f50-bfa02538cce5.png)


Co-authored-by: qthree <qthree3@gmail.com>
This commit is contained in:
bors[bot]
2020-09-10 04:34:35 +00:00
committed by GitHub
3 changed files with 221 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
# hello-windows
This example renders a set of 16 windows, with a differently colored background
## To Run
```
cargo run --example hello-windows
```
## Screenshots
![16 windows](./screenshot.png)

View File

@@ -0,0 +1,208 @@
use std::collections::HashMap;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Window, WindowId},
};
struct ViewportDesc {
window: Window,
background: wgpu::Color,
surface: wgpu::Surface,
}
struct Viewport {
desc: ViewportDesc,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
}
impl ViewportDesc {
fn new(window: Window, background: wgpu::Color, instance: &wgpu::Instance) -> Self {
let surface = unsafe { instance.create_surface(&window) };
Self {
window,
background,
surface,
}
}
fn build(self, device: &wgpu::Device, swapchain_format: wgpu::TextureFormat) -> Viewport {
let size = self.window.inner_size();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: swapchain_format,
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&self.surface, &sc_desc);
Viewport {
desc: self,
sc_desc,
swap_chain,
}
}
}
impl Viewport {
fn resize(&mut self, device: &wgpu::Device, size: winit::dpi::PhysicalSize<u32>) {
self.sc_desc.width = size.width;
self.sc_desc.height = size.height;
self.swap_chain = device.create_swap_chain(&self.desc.surface, &self.sc_desc);
}
fn get_current_frame(&mut self) -> wgpu::SwapChainTexture {
self.swap_chain
.get_current_frame()
.expect("Failed to acquire next swap chain texture")
.output
}
}
async fn run(
event_loop: EventLoop<()>,
viewports: Vec<(Window, wgpu::Color)>,
swapchain_format: wgpu::TextureFormat,
) {
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let viewports: Vec<_> = viewports
.into_iter()
.map(|(window, color)| ViewportDesc::new(window, color, &instance))
.collect();
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
// Request an adapter which can render to our surface
compatible_surface: viewports.first().map(|desc| &desc.surface),
})
.await
.expect("Failed to find an appropiate adapter");
// Create the logical device and command queue
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,
},
None,
)
.await
.expect("Failed to create device");
let mut viewports: HashMap<WindowId, Viewport> = viewports
.into_iter()
.map(|desc| (desc.window.id(), desc.build(&device, swapchain_format)))
.collect();
event_loop.run(move |event, _, control_flow| {
// Have the closure take ownership of the resources.
// `event_loop.run` never returns, therefore we must do this to ensure
// the resources are properly cleaned up.
let _ = (&instance, &adapter);
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
window_id,
event: WindowEvent::Resized(size),
..
} => {
// Recreate the swap chain with the new size
if let Some(viewport) = viewports.get_mut(&window_id) {
viewport.resize(&device, size);
}
}
Event::RedrawRequested(window_id) => {
if let Some(viewport) = viewports.get_mut(&window_id) {
let frame = viewport.get_current_frame();
let mut encoder = device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let _rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(viewport.desc.background),
store: true,
},
}],
depth_stencil_attachment: None,
});
}
queue.submit(Some(encoder.finish()));
}
}
Event::WindowEvent {
window_id,
event: WindowEvent::CloseRequested,
..
} => {
viewports.remove(&window_id);
if viewports.is_empty() {
*control_flow = ControlFlow::Exit
}
}
_ => {}
}
});
}
fn main() {
#[cfg(not(target_arch = "wasm32"))]
{
const WINDOW_SIZE: u32 = 128;
const WINDOW_PADDING: u32 = 16;
const WINDOW_TITLEBAR: u32 = 32;
const WINDOW_OFFSET: u32 = WINDOW_SIZE + WINDOW_PADDING;
const ROWS: u32 = 4;
const COLUMNS: u32 = 4;
let event_loop = EventLoop::new();
let mut viewports = Vec::with_capacity((ROWS * COLUMNS) as usize);
for row in 0..ROWS {
for column in 0..COLUMNS {
let window = winit::window::WindowBuilder::new()
.with_title(format!("x{}y{}", column, row))
.with_inner_size(winit::dpi::PhysicalSize::new(WINDOW_SIZE, WINDOW_SIZE))
.build(&event_loop)
.unwrap();
window.set_outer_position(winit::dpi::PhysicalPosition::new(
WINDOW_PADDING + column * WINDOW_OFFSET,
WINDOW_PADDING + row * (WINDOW_OFFSET + WINDOW_TITLEBAR),
));
fn frac(index: u32, max: u32) -> f64 {
index as f64 / max as f64
}
viewports.push((
window,
wgpu::Color {
r: frac(row, ROWS),
g: 0.5 - frac(row * column, ROWS * COLUMNS) * 0.5,
b: frac(column, COLUMNS),
a: 1.0,
},
))
}
}
subscriber::initialize_default_subscriber(None);
// Temporarily avoid srgb formats for the swapchain on the web
futures::executor::block_on(run(
event_loop,
viewports,
wgpu::TextureFormat::Bgra8UnormSrgb,
));
}
#[cfg(target_arch = "wasm32")]
{
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
panic!("wasm32 is not supported")
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB