mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
Merged wgpu runners (#241)
* Added clap to switch between shaders * Merged wgpu runners * tested something related to async which i forgot to udno * clippy * xamprocky suggestion
This commit is contained in:
parent
28e71d9932
commit
2d75e0473f
25
Cargo.lock
generated
25
Cargo.lock
generated
@ -649,17 +649,6 @@ dependencies = [
|
|||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "example-runner-wgpu-compute"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"futures",
|
|
||||||
"rspirv 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"spirv-builder",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"wgpu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
@ -1960,18 +1949,6 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rspirv"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "31b11de7481ced3d22182a2be7670323028b38a7cc3457e470f91d144947fba4"
|
|
||||||
dependencies = [
|
|
||||||
"derive_more",
|
|
||||||
"fxhash",
|
|
||||||
"num-traits",
|
|
||||||
"spirv_headers 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rspirv"
|
name = "rspirv"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -1990,7 +1967,7 @@ dependencies = [
|
|||||||
"bimap",
|
"bimap",
|
||||||
"pipe",
|
"pipe",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"rspirv 0.7.0 (git+https://github.com/gfx-rs/rspirv.git?rev=f11f8797bd4df2d1d22cf10767b39a5119c57551)",
|
"rspirv",
|
||||||
"spirv-tools",
|
"spirv-tools",
|
||||||
"tar",
|
"tar",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
@ -3,7 +3,6 @@ members = [
|
|||||||
"examples/runners/cpu",
|
"examples/runners/cpu",
|
||||||
"examples/runners/ash",
|
"examples/runners/ash",
|
||||||
"examples/runners/wgpu",
|
"examples/runners/wgpu",
|
||||||
"examples/runners/wgpu-compute",
|
|
||||||
"examples/shaders/sky-shader",
|
"examples/shaders/sky-shader",
|
||||||
"examples/shaders/simplest-shader",
|
"examples/shaders/simplest-shader",
|
||||||
"examples/shaders/compute-shader",
|
"examples/shaders/compute-shader",
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "example-runner-wgpu-compute"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Embark <opensource@embark-studios.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
|
|
||||||
# See rustc_codegen_spirv/Cargo.toml for details on these features
|
|
||||||
[features]
|
|
||||||
default = ["use-compiled-tools"]
|
|
||||||
use-installed-tools = ["spirv-builder/use-installed-tools"]
|
|
||||||
use-compiled-tools = ["spirv-builder/use-compiled-tools"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
wgpu = "0.6.0"
|
|
||||||
futures = { version = "0.3", default-features = false, features = ["std", "executor"] }
|
|
||||||
rspirv = "0.7.0"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
spirv-builder = { path = "../../../crates/spirv-builder" }
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
||||||
wasm-bindgen-futures = "0.4.18"
|
|
@ -1,8 +0,0 @@
|
|||||||
use spirv_builder::SpirvBuilder;
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
// This will set the env var `compute_shader.spv` to a spir-v file that can be include!()'d
|
|
||||||
SpirvBuilder::new("../../shaders/compute-shader").build()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -11,5 +11,6 @@ fn build_shader(path_to_create: &str) -> Result<(), Box<dyn Error>> {
|
|||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
build_shader("../../shaders/sky-shader")?;
|
build_shader("../../shaders/sky-shader")?;
|
||||||
build_shader("../../shaders/simplest-shader")?;
|
build_shader("../../shaders/simplest-shader")?;
|
||||||
|
build_shader("../../shaders/compute-shader")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
fn shader_module() -> wgpu::ShaderModuleSource<'static> {
|
use super::{shader_module, Options};
|
||||||
wgpu::include_spirv!(env!("compute_shader.spv"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_device_queue() -> (wgpu::Device, wgpu::Queue) {
|
fn create_device_queue() -> (wgpu::Device, wgpu::Queue) {
|
||||||
async fn create_device_queue_async() -> (wgpu::Device, wgpu::Queue) {
|
async fn create_device_queue_async() -> (wgpu::Device, wgpu::Queue) {
|
||||||
@ -25,21 +23,20 @@ fn create_device_queue() -> (wgpu::Device, wgpu::Queue) {
|
|||||||
.await
|
.await
|
||||||
.expect("Failed to create device")
|
.expect("Failed to create device")
|
||||||
}
|
}
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
cfg_if::cfg_if! {
|
||||||
{
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
return futures::executor::block_on(create_device_queue_async());
|
wasm_bindgen_futures::spawn_local(create_device_queue_async())
|
||||||
};
|
} else {
|
||||||
#[cfg(target_arch = "wasm32")]
|
futures::executor::block_on(create_device_queue_async())
|
||||||
{
|
}
|
||||||
return wasm_bindgen_futures::spawn_local(create_device_queue_async());
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
pub fn start(options: &Options) {
|
||||||
let (device, queue) = create_device_queue();
|
let (device, queue) = create_device_queue();
|
||||||
|
|
||||||
// Load the shaders from disk
|
// Load the shaders from disk
|
||||||
let module = device.create_shader_module(shader_module());
|
let module = device.create_shader_module(shader_module(options.shader));
|
||||||
|
|
||||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: None,
|
label: None,
|
211
examples/runners/wgpu/src/graphics.rs
Normal file
211
examples/runners/wgpu/src/graphics.rs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
use super::{shader_module, Options};
|
||||||
|
use winit::{
|
||||||
|
event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||||
|
event_loop::{ControlFlow, EventLoop},
|
||||||
|
window::Window,
|
||||||
|
};
|
||||||
|
|
||||||
|
async fn run(
|
||||||
|
options: &Options,
|
||||||
|
event_loop: EventLoop<()>,
|
||||||
|
window: Window,
|
||||||
|
swapchain_format: wgpu::TextureFormat,
|
||||||
|
) {
|
||||||
|
let size = window.inner_size();
|
||||||
|
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
|
||||||
|
|
||||||
|
// Wait for Resumed event on Android; the surface is only needed early to
|
||||||
|
// find an adapter that can render to this surface.
|
||||||
|
let mut surface = if cfg!(target_os = "android") {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(unsafe { instance.create_surface(&window) })
|
||||||
|
};
|
||||||
|
|
||||||
|
let adapter = instance
|
||||||
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
|
power_preference: wgpu::PowerPreference::default(),
|
||||||
|
// Request an adapter which can render to our surface
|
||||||
|
compatible_surface: surface.as_ref(),
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.expect("Failed to find an appropriate 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");
|
||||||
|
|
||||||
|
// Load the shaders from disk
|
||||||
|
let module = device.create_shader_module(shader_module(options.shader));
|
||||||
|
|
||||||
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
label: None,
|
||||||
|
bind_group_layouts: &[],
|
||||||
|
push_constant_ranges: &[],
|
||||||
|
});
|
||||||
|
|
||||||
|
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
|
label: None,
|
||||||
|
layout: Some(&pipeline_layout),
|
||||||
|
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||||
|
module: &module,
|
||||||
|
entry_point: "main_vs",
|
||||||
|
},
|
||||||
|
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||||
|
module: &module,
|
||||||
|
entry_point: "main_fs",
|
||||||
|
}),
|
||||||
|
// Use the default rasterizer state: no culling, no depth bias
|
||||||
|
rasterization_state: None,
|
||||||
|
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||||
|
color_states: &[swapchain_format.into()],
|
||||||
|
depth_stencil_state: None,
|
||||||
|
vertex_state: wgpu::VertexStateDescriptor {
|
||||||
|
index_format: wgpu::IndexFormat::Uint16,
|
||||||
|
vertex_buffers: &[],
|
||||||
|
},
|
||||||
|
sample_count: 1,
|
||||||
|
sample_mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut sc_desc = wgpu::SwapChainDescriptor {
|
||||||
|
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
|
format: swapchain_format,
|
||||||
|
width: size.width,
|
||||||
|
height: size.height,
|
||||||
|
present_mode: wgpu::PresentMode::Mailbox,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut swap_chain = surface
|
||||||
|
.as_ref()
|
||||||
|
.map(|surface| device.create_swap_chain(&surface, &sc_desc));
|
||||||
|
|
||||||
|
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, &module, &pipeline_layout);
|
||||||
|
|
||||||
|
*control_flow = ControlFlow::Wait;
|
||||||
|
match event {
|
||||||
|
Event::Resumed => {
|
||||||
|
let s = unsafe { instance.create_surface(&window) };
|
||||||
|
swap_chain = Some(device.create_swap_chain(&s, &sc_desc));
|
||||||
|
surface = Some(s);
|
||||||
|
}
|
||||||
|
Event::Suspended => {
|
||||||
|
surface = None;
|
||||||
|
swap_chain = None;
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::Resized(size),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// Recreate the swap chain with the new size
|
||||||
|
sc_desc.width = size.width;
|
||||||
|
sc_desc.height = size.height;
|
||||||
|
if let Some(surface) = &surface {
|
||||||
|
swap_chain = Some(device.create_swap_chain(surface, &sc_desc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::RedrawRequested(_) => {
|
||||||
|
if let Some(swap_chain) = &mut swap_chain {
|
||||||
|
let frame = swap_chain
|
||||||
|
.get_current_frame()
|
||||||
|
.expect("Failed to acquire next swap chain texture")
|
||||||
|
.output;
|
||||||
|
let mut encoder = device
|
||||||
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||||
|
{
|
||||||
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: &frame.view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN),
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
});
|
||||||
|
rpass.set_pipeline(&render_pipeline);
|
||||||
|
rpass.draw(0..3, 0..1);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.submit(Some(encoder.finish()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => *control_flow = ControlFlow::Exit,
|
||||||
|
Event::WindowEvent {
|
||||||
|
event:
|
||||||
|
WindowEvent::KeyboardInput {
|
||||||
|
input:
|
||||||
|
KeyboardInput {
|
||||||
|
virtual_keycode: Some(VirtualKeyCode::Escape),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} => *control_flow = ControlFlow::Exit,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(options: &Options) {
|
||||||
|
let event_loop = EventLoop::new();
|
||||||
|
let window = winit::window::WindowBuilder::new()
|
||||||
|
.with_title("Rust GPU - wgpu")
|
||||||
|
.with_inner_size(winit::dpi::LogicalSize::new(1280.0, 720.0))
|
||||||
|
.build(&event_loop)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_arch = "wasm32")] {
|
||||||
|
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||||
|
console_log::init().expect("could not initialize logger");
|
||||||
|
use winit::platform::web::WindowExtWebSys;
|
||||||
|
// On wasm, append the canvas to the document body
|
||||||
|
web_sys::window()
|
||||||
|
.and_then(|win| win.document())
|
||||||
|
.and_then(|doc| doc.body())
|
||||||
|
.and_then(|body| {
|
||||||
|
body.append_child(&web_sys::Element::from(window.canvas()))
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.expect("couldn't append canvas to document body");
|
||||||
|
// Temporarily avoid srgb formats for the swapchain on the web
|
||||||
|
wasm_bindgen_futures::spawn_local(run(
|
||||||
|
event_loop,
|
||||||
|
window,
|
||||||
|
wgpu::TextureFormat::Bgra8Unorm,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
wgpu_subscriber::initialize_default_subscriber(None);
|
||||||
|
futures::executor::block_on(run(
|
||||||
|
options,
|
||||||
|
event_loop,
|
||||||
|
window,
|
||||||
|
if cfg!(target_os = "android") {
|
||||||
|
wgpu::TextureFormat::Rgba8UnormSrgb
|
||||||
|
} else {
|
||||||
|
wgpu::TextureFormat::Bgra8UnormSrgb
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,234 +1,41 @@
|
|||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use strum::{Display, EnumString};
|
use strum::{Display, EnumString};
|
||||||
use winit::{
|
|
||||||
event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
|
||||||
event_loop::{ControlFlow, EventLoop},
|
|
||||||
window::Window,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(EnumString, Display)]
|
mod compute;
|
||||||
enum RustGPUShader {
|
mod graphics;
|
||||||
|
|
||||||
|
#[derive(EnumString, Display, PartialEq, Copy, Clone)]
|
||||||
|
pub enum RustGPUShader {
|
||||||
Simplest,
|
Simplest,
|
||||||
Sky,
|
Sky,
|
||||||
|
Compute,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shader_module(shader: RustGPUShader) -> wgpu::ShaderModuleSource<'static> {
|
fn shader_module(shader: RustGPUShader) -> wgpu::ShaderModuleSource<'static> {
|
||||||
match shader {
|
match shader {
|
||||||
RustGPUShader::Simplest => wgpu::include_spirv!(env!("simplest_shader.spv")),
|
RustGPUShader::Simplest => wgpu::include_spirv!(env!("simplest_shader.spv")),
|
||||||
RustGPUShader::Sky => wgpu::include_spirv!(env!("sky_shader.spv")),
|
RustGPUShader::Sky => wgpu::include_spirv!(env!("sky_shader.spv")),
|
||||||
|
RustGPUShader::Compute => wgpu::include_spirv!(env!("compute_shader.spv")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clap)]
|
fn is_compute_shader(shader: RustGPUShader) -> bool {
|
||||||
struct Options {
|
shader == RustGPUShader::Compute
|
||||||
#[clap(short, long, default_value = "Sky")]
|
|
||||||
shader: RustGPUShader,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(
|
#[derive(Clap)]
|
||||||
options: Options,
|
pub struct Options {
|
||||||
event_loop: EventLoop<()>,
|
#[clap(short, long, default_value = "Sky")]
|
||||||
window: Window,
|
shader: RustGPUShader,
|
||||||
swapchain_format: wgpu::TextureFormat,
|
|
||||||
) {
|
|
||||||
let size = window.inner_size();
|
|
||||||
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
|
|
||||||
|
|
||||||
// Wait for Resumed event on Android; the surface is only needed early to
|
|
||||||
// find an adapter that can render to this surface.
|
|
||||||
let mut surface = if cfg!(target_os = "android") {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(unsafe { instance.create_surface(&window) })
|
|
||||||
};
|
|
||||||
|
|
||||||
let adapter = instance
|
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
|
||||||
power_preference: wgpu::PowerPreference::default(),
|
|
||||||
// Request an adapter which can render to our surface
|
|
||||||
compatible_surface: surface.as_ref(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.expect("Failed to find an appropriate 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");
|
|
||||||
|
|
||||||
// Load the shaders from disk
|
|
||||||
let module = device.create_shader_module(shader_module(options.shader));
|
|
||||||
|
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
||||||
label: None,
|
|
||||||
bind_group_layouts: &[],
|
|
||||||
push_constant_ranges: &[],
|
|
||||||
});
|
|
||||||
|
|
||||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
|
||||||
label: None,
|
|
||||||
layout: Some(&pipeline_layout),
|
|
||||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
|
||||||
module: &module,
|
|
||||||
entry_point: "main_vs",
|
|
||||||
},
|
|
||||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
|
||||||
module: &module,
|
|
||||||
entry_point: "main_fs",
|
|
||||||
}),
|
|
||||||
// Use the default rasterizer state: no culling, no depth bias
|
|
||||||
rasterization_state: None,
|
|
||||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
|
||||||
color_states: &[swapchain_format.into()],
|
|
||||||
depth_stencil_state: None,
|
|
||||||
vertex_state: wgpu::VertexStateDescriptor {
|
|
||||||
index_format: wgpu::IndexFormat::Uint16,
|
|
||||||
vertex_buffers: &[],
|
|
||||||
},
|
|
||||||
sample_count: 1,
|
|
||||||
sample_mask: !0,
|
|
||||||
alpha_to_coverage_enabled: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut sc_desc = wgpu::SwapChainDescriptor {
|
|
||||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
|
||||||
format: swapchain_format,
|
|
||||||
width: size.width,
|
|
||||||
height: size.height,
|
|
||||||
present_mode: wgpu::PresentMode::Mailbox,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut swap_chain = surface
|
|
||||||
.as_ref()
|
|
||||||
.map(|surface| device.create_swap_chain(&surface, &sc_desc));
|
|
||||||
|
|
||||||
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, &module, &pipeline_layout);
|
|
||||||
|
|
||||||
*control_flow = ControlFlow::Wait;
|
|
||||||
match event {
|
|
||||||
Event::Resumed => {
|
|
||||||
let s = unsafe { instance.create_surface(&window) };
|
|
||||||
swap_chain = Some(device.create_swap_chain(&s, &sc_desc));
|
|
||||||
surface = Some(s);
|
|
||||||
}
|
|
||||||
Event::Suspended => {
|
|
||||||
surface = None;
|
|
||||||
swap_chain = None;
|
|
||||||
}
|
|
||||||
Event::WindowEvent {
|
|
||||||
event: WindowEvent::Resized(size),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// Recreate the swap chain with the new size
|
|
||||||
sc_desc.width = size.width;
|
|
||||||
sc_desc.height = size.height;
|
|
||||||
if let Some(surface) = &surface {
|
|
||||||
swap_chain = Some(device.create_swap_chain(surface, &sc_desc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::RedrawRequested(_) => {
|
|
||||||
if let Some(swap_chain) = &mut swap_chain {
|
|
||||||
let frame = swap_chain
|
|
||||||
.get_current_frame()
|
|
||||||
.expect("Failed to acquire next swap chain texture")
|
|
||||||
.output;
|
|
||||||
let mut encoder = device
|
|
||||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
|
||||||
{
|
|
||||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
|
||||||
attachment: &frame.view,
|
|
||||||
resolve_target: None,
|
|
||||||
ops: wgpu::Operations {
|
|
||||||
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN),
|
|
||||||
store: true,
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
depth_stencil_attachment: None,
|
|
||||||
});
|
|
||||||
rpass.set_pipeline(&render_pipeline);
|
|
||||||
rpass.draw(0..3, 0..1);
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.submit(Some(encoder.finish()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::WindowEvent {
|
|
||||||
event: WindowEvent::CloseRequested,
|
|
||||||
..
|
|
||||||
} => *control_flow = ControlFlow::Exit,
|
|
||||||
Event::WindowEvent {
|
|
||||||
event:
|
|
||||||
WindowEvent::KeyboardInput {
|
|
||||||
input:
|
|
||||||
KeyboardInput {
|
|
||||||
virtual_keycode: Some(VirtualKeyCode::Escape),
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
} => *control_flow = ControlFlow::Exit,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
|
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let options: Options = Options::parse();
|
let options: Options = Options::parse();
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
if is_compute_shader(options.shader) {
|
||||||
let window = winit::window::WindowBuilder::new()
|
compute::start(&options)
|
||||||
.with_title("Rust GPU - wgpu")
|
} else {
|
||||||
.with_inner_size(winit::dpi::LogicalSize::new(1280.0, 720.0))
|
graphics::start(&options);
|
||||||
.build(&event_loop)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(target_arch = "wasm32")] {
|
|
||||||
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
|
||||||
console_log::init().expect("could not initialize logger");
|
|
||||||
use winit::platform::web::WindowExtWebSys;
|
|
||||||
// On wasm, append the canvas to the document body
|
|
||||||
web_sys::window()
|
|
||||||
.and_then(|win| win.document())
|
|
||||||
.and_then(|doc| doc.body())
|
|
||||||
.and_then(|body| {
|
|
||||||
body.append_child(&web_sys::Element::from(window.canvas()))
|
|
||||||
.ok()
|
|
||||||
})
|
|
||||||
.expect("couldn't append canvas to document body");
|
|
||||||
// Temporarily avoid srgb formats for the swapchain on the web
|
|
||||||
wasm_bindgen_futures::spawn_local(run(
|
|
||||||
event_loop,
|
|
||||||
window,
|
|
||||||
wgpu::TextureFormat::Bgra8Unorm,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
wgpu_subscriber::initialize_default_subscriber(None);
|
|
||||||
futures::executor::block_on(run(
|
|
||||||
options,
|
|
||||||
event_loop,
|
|
||||||
window,
|
|
||||||
if cfg!(target_os = "android") {
|
|
||||||
wgpu::TextureFormat::Rgba8UnormSrgb
|
|
||||||
} else {
|
|
||||||
wgpu::TextureFormat::Bgra8UnormSrgb
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user