Merge branch '0.10'

pull/229/head
Ben Hansen 3 years ago
commit 5ddd876d4f

1025
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,12 +1,13 @@
[workspace]
resolver = "2"
members = [
# beginner tutorials
# # beginner tutorials
"code/beginner/*",
# intermediate tutorials
# # intermediate tutorials
"code/intermediate/*",
# showcase
# # showcase
"code/showcase/*",
]
exclude = [

@ -17,5 +17,5 @@ winit = "0.25"
cgmath = "0.18"
env_logger = "0.9"
log = "0.4"
wgpu = "0.9"
wgpu = "0.10"
pollster = "0.2"

@ -1,5 +1,5 @@
[package]
name = "tutorial2-swapchain"
name = "tutorial2-surface"
version = "0.1.0"
authors = ["Ben Hansen <bhbenjaminhansen@gmail.com>"]
edition = "2018"
@ -12,12 +12,15 @@ winit = "0.25"
cgmath = "0.18"
env_logger = "0.9"
log = "0.4"
wgpu = "0.9"
wgpu = "0.10"
# wgpu = { version = "0.10", features=["trace"]}
# wgpu = { git = "https://github.com/gfx-rs/wgpu/"}
# wgpu = { git = "https://github.com/gfx-rs/wgpu/", features=["trace"]}
pollster = "0.2"
[[bin]]
name = "tutorial2-swapchain"
name = "tutorial2-surface"
path = "src/main.rs"
[[bin]]

@ -7,11 +7,14 @@ use winit::{
};
struct State {
#[allow(dead_code)]
instance: wgpu::Instance,
#[allow(dead_code)]
adapter: wgpu::Adapter,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
clear_color: wgpu::Color,
}
@ -22,7 +25,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -44,26 +47,25 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let clear_color = wgpu::Color::BLACK;
Self {
instance,
adapter,
surface,
device,
queue,
sc_desc,
swap_chain,
config,
clear_color,
size,
}
}
@ -71,9 +73,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -94,8 +96,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -107,7 +112,7 @@ impl State {
let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(self.clear_color),
@ -129,7 +134,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -165,10 +170,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -10,8 +10,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
}
@ -21,7 +20,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -38,26 +37,26 @@ impl State {
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
},
None, // Trace path
// Some(&std::path::Path::new("trace")), // Trace path
None,
)
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
Self {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
}
}
@ -65,9 +64,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -78,8 +77,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -91,7 +93,7 @@ impl State {
let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -118,7 +120,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state: State = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -155,10 +157,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -10,7 +10,7 @@ winit = "0.25"
cgmath = "0.18"
env_logger = "0.9"
log = "0.4"
wgpu = "0.9"
wgpu = "0.10"
pollster = "0.2"
# NEW!

@ -10,8 +10,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
challenge_render_pipeline: wgpu::RenderPipeline,
@ -24,7 +23,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -46,18 +45,17 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -80,12 +78,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -110,7 +108,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Challenge Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("challenge.wgsl").into()),
});
@ -127,9 +124,9 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -155,8 +152,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
challenge_render_pipeline,
use_color,
@ -167,9 +163,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -193,8 +189,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -206,7 +205,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -240,7 +239,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -276,10 +275,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -10,8 +10,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
// NEW!
render_pipeline: wgpu::RenderPipeline,
@ -23,7 +22,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -45,18 +44,17 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -79,12 +77,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -112,8 +110,7 @@ impl State {
device,
queue,
size,
sc_desc,
swap_chain,
config,
render_pipeline,
}
}
@ -121,9 +118,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -134,8 +131,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -147,7 +147,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -177,7 +177,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -213,10 +213,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -9,7 +9,7 @@ edition = "2018"
image = "0.23"
cgmath = "0.18"
winit = "0.25"
wgpu = "0.9"
wgpu = "0.10"
env_logger = "0.9"
log = "0.4"
pollster = "0.2"

@ -18,7 +18,7 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -64,8 +64,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
@ -87,7 +86,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -109,18 +108,17 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -143,12 +141,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -174,12 +172,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -206,12 +204,12 @@ impl State {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Challenge Vertex Buffer"),
contents: bytemuck::cast_slice(&challenge_verts),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let challenge_index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Challenge Index Buffer"),
contents: bytemuck::cast_slice(&challenge_indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let use_complex = false;
@ -220,8 +218,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
index_buffer,
@ -237,9 +234,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -263,8 +260,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -276,7 +276,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -319,7 +319,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -355,10 +355,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -18,7 +18,7 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -64,8 +64,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
// NEW!
@ -80,7 +79,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -102,18 +101,17 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -136,12 +134,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -167,12 +165,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -180,8 +178,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -193,9 +190,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -206,8 +203,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -219,7 +219,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -251,7 +251,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -287,10 +287,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -14,7 +14,7 @@ env_logger = "0.9"
log = "0.4"
pollster = "0.2"
image = "0.23"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -21,7 +21,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -67,8 +67,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -89,7 +88,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -110,21 +109,21 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -134,7 +133,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -186,7 +185,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -209,12 +207,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -240,12 +238,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -253,8 +251,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
index_buffer,
@ -271,9 +268,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -297,8 +294,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -310,7 +310,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -349,7 +349,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -385,10 +385,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -21,7 +21,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -67,8 +67,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -86,7 +85,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -107,14 +106,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -125,7 +124,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -135,7 +134,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -163,7 +162,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -186,12 +184,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -217,12 +215,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -230,8 +228,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -245,9 +242,9 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
@ -258,8 +255,11 @@ impl State {
fn update(&mut self) {}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -271,7 +271,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -304,7 +304,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -340,10 +340,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -41,11 +41,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -12,7 +12,7 @@ env_logger = "0.9"
log = "0.4"
pollster = "0.2"
image = "0.23"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -21,7 +21,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -228,8 +228,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
@ -251,7 +250,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -272,14 +271,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -290,7 +289,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -300,7 +299,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -330,7 +329,7 @@ impl State {
eye: (0.0, 1.0, 2.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -344,14 +343,14 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -373,7 +372,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -396,12 +394,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -427,12 +425,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -440,8 +438,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
index_buffer,
@ -460,12 +457,12 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera_staging.camera.aspect =
self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.config.width as f32 / self.config.height as f32;
}
}
@ -485,8 +482,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -498,7 +498,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -532,7 +532,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -568,10 +568,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -21,7 +21,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -212,8 +212,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -236,7 +235,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -257,14 +256,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -275,7 +274,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -285,7 +284,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -315,7 +314,7 @@ impl State {
eye: (0.0, 1.0, 2.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -328,14 +327,14 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -357,7 +356,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -380,12 +378,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -411,12 +409,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -424,8 +422,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -444,11 +441,11 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
}
}
@ -466,8 +463,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -479,7 +479,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -513,7 +513,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -549,10 +549,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -41,11 +41,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -12,7 +12,7 @@ env_logger = "0.9"
log = "0.4"
pollster = "0.2"
image = "0.23"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -22,7 +22,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -245,7 +245,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -280,8 +280,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
@ -333,7 +332,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -354,14 +353,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -372,7 +371,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -382,7 +381,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -412,7 +411,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -425,7 +424,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let instances = (0..NUM_INSTANCES_PER_ROW)
@ -457,14 +456,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -486,7 +485,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -509,12 +507,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -540,12 +538,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -553,8 +551,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
index_buffer,
@ -575,11 +572,11 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
}
}
@ -613,8 +610,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -626,7 +626,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -661,7 +661,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -697,10 +697,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -29,7 +29,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -235,7 +235,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -270,8 +270,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -297,7 +296,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -318,14 +317,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -336,7 +335,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -346,7 +345,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -376,7 +375,7 @@ impl State {
eye: (0.0, 5.0, 10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -389,7 +388,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let instances = (0..NUM_INSTANCES_PER_ROW)
@ -421,14 +420,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -450,7 +449,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -473,12 +471,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -504,12 +502,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -517,8 +515,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -540,11 +537,11 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
}
}
@ -562,8 +559,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -575,7 +575,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -611,7 +611,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -647,10 +647,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -41,11 +41,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -12,7 +12,7 @@ env_logger = "0.9"
pollster = "0.2"
image = "0.23"
log = "0.4"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -22,7 +22,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -266,7 +266,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -308,8 +308,8 @@ struct DepthPass {
}
impl DepthPass {
fn new(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self {
let texture = texture::Texture::create_depth_texture(device, sc_desc, "depth_texture");
fn new(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration) -> Self {
let texture = texture::Texture::create_depth_texture(device, config, "depth_texture");
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Depth Pass Layout"),
@ -322,7 +322,7 @@ impl DepthPass {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
},
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
@ -331,7 +331,7 @@ impl DepthPass {
comparison: true,
filtering: true,
},
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
},
],
});
@ -354,12 +354,12 @@ impl DepthPass {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Depth Pass VB"),
contents: bytemuck::cast_slice(DEPTH_VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Depth Pass IB"),
contents: bytemuck::cast_slice(DEPTH_INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -370,7 +370,6 @@ impl DepthPass {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shadow Display Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("challenge.wgsl").into()),
});
@ -386,12 +385,12 @@ impl DepthPass {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -425,8 +424,8 @@ impl DepthPass {
}
}
fn resize(&mut self, device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) {
self.texture = texture::Texture::create_depth_texture(device, sc_desc, "depth_texture");
fn resize(&mut self, device: &wgpu::Device, config: &wgpu::SurfaceConfiguration) {
self.texture = texture::Texture::create_depth_texture(device, config, "depth_texture");
self.bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &self.layout,
entries: &[
@ -443,11 +442,11 @@ impl DepthPass {
});
}
fn render(&self, frame: &wgpu::SwapChainTexture, encoder: &mut wgpu::CommandEncoder) {
fn render(&self, view: &wgpu::TextureView, encoder: &mut wgpu::CommandEncoder) {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Depth Visual Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
@ -468,8 +467,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
@ -495,7 +493,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -516,14 +514,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -534,7 +532,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -544,7 +542,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -574,7 +572,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -587,7 +585,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let instances = (0..NUM_INSTANCES_PER_ROW)
@ -619,14 +617,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -648,7 +646,6 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
@ -671,12 +668,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -712,23 +709,22 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
let depth_pass = DepthPass::new(&device, &sc_desc);
let depth_pass = DepthPass::new(&device, &config);
Self {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
index_buffer,
@ -749,13 +745,13 @@ impl State {
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_pass.resize(&self.device, &self.sc_desc);
self.surface.configure(&self.device, &self.config);
self.depth_pass.resize(&self.device, &self.config);
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
}
}
@ -773,8 +769,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -786,7 +785,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -817,7 +816,7 @@ impl State {
render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as u32);
}
self.depth_pass.render(&frame, &mut encoder);
self.depth_pass.render(&view, &mut encoder);
self.queue.submit(iter::once(encoder.finish()));
@ -830,7 +829,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -866,10 +865,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -22,7 +22,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -244,7 +244,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -279,8 +279,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -307,7 +306,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -328,14 +327,14 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png");
let diffuse_texture =
@ -346,7 +345,7 @@ impl State {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -356,7 +355,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -386,7 +385,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -399,7 +398,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let instances = (0..NUM_INSTANCES_PER_ROW)
@ -431,14 +430,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -460,12 +459,11 @@ impl State {
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -486,12 +484,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -523,12 +521,12 @@ impl State {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
let num_indices = INDICES.len() as u32;
@ -536,8 +534,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -559,16 +556,13 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
// NEW!
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -586,8 +580,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -599,7 +596,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -640,7 +637,7 @@ fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -676,10 +673,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -14,12 +14,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -29,7 +29,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -84,11 +84,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -13,7 +13,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "3.0"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -188,7 +188,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -223,8 +223,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
@ -245,7 +244,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -267,22 +266,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -292,7 +291,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -307,7 +306,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -320,7 +319,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -350,14 +349,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -386,16 +385,13 @@ impl State {
)
.unwrap();
// let vs_module = device.create_shader_module(&wgpu::include_spirv!("shader.vert.spv"));
// let fs_module = device.create_shader_module(&wgpu::include_spirv!("shader.frag.spv"));
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("shader.wgsl"),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
flags: wgpu::ShaderFlags::VALIDATION,
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -416,12 +412,12 @@ impl State {
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState {
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -454,8 +450,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
obj_model,
@ -472,16 +467,13 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
fn input(&mut self, event: &WindowEvent) -> bool {
@ -498,8 +490,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -511,7 +506,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -557,7 +552,7 @@ fn main() {
.build(&event_loop)
.unwrap();
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
event_loop.run(move |event, _, control_flow| {
@ -594,10 +589,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -23,7 +23,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -135,12 +135,12 @@ impl Model {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -26,12 +26,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -41,7 +41,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -83,7 +83,7 @@ impl Texture {
label: Option<&str>,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -97,11 +97,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -13,7 +13,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "3.0"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -194,7 +194,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -253,8 +253,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
camera: Camera,
@ -300,7 +299,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -336,7 +335,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -357,22 +356,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -382,7 +381,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -397,7 +396,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -411,7 +410,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -441,14 +440,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -486,14 +485,14 @@ impl State {
let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -514,7 +513,7 @@ impl State {
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -530,13 +529,12 @@ impl State {
let render_pipeline = {
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Normal Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
};
create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
shader,
@ -551,13 +549,12 @@ impl State {
});
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Light Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()),
};
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
shader,
@ -568,8 +565,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
obj_model,
camera,
@ -590,16 +586,13 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -629,8 +622,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -642,7 +638,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -729,10 +725,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -23,7 +23,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -135,12 +135,12 @@ impl Model {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -26,12 +26,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -41,7 +41,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -83,7 +83,7 @@ impl Texture {
label: Option<&str>,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -97,11 +97,12 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -13,7 +13,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "3.0"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -193,7 +193,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -252,8 +252,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
camera: Camera,
@ -301,7 +300,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -337,7 +336,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -358,22 +357,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -383,7 +382,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -393,7 +392,7 @@ impl State {
// normal map
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -403,7 +402,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -418,7 +417,7 @@ impl State {
eye: (0.0, 5.0, -10.0).into(),
target: (0.0, 0.0, 0.0).into(),
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -432,7 +431,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -462,14 +461,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -507,14 +506,14 @@ impl State {
let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -535,7 +534,7 @@ impl State {
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -551,13 +550,12 @@ impl State {
let render_pipeline = {
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Normal Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
};
create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
shader,
@ -572,13 +570,12 @@ impl State {
});
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Light Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()),
};
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
shader,
@ -619,8 +616,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
obj_model,
camera,
@ -643,16 +639,13 @@ impl State {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.camera.aspect = self.sc_desc.width as f32 / self.sc_desc.height as f32;
self.camera.aspect = self.config.width as f32 / self.config.height as f32;
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -682,8 +675,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -695,7 +691,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -782,10 +778,10 @@ fn main() {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -26,7 +26,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -256,12 +256,12 @@ impl Model {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -27,12 +27,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -42,7 +42,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -86,7 +86,7 @@ impl Texture {
is_normal_map: bool,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -104,11 +104,12 @@ impl Texture {
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -13,7 +13,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "3.0"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -70,7 +70,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -129,8 +129,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
camera: camera::Camera, // UPDATED!
@ -181,7 +180,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -217,7 +216,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -238,22 +237,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -263,7 +262,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -273,7 +272,7 @@ impl State {
// normal map
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -283,7 +282,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -297,7 +296,7 @@ impl State {
// UPDATED!
let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
let projection =
camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
camera::Projection::new(config.width, config.height, cgmath::Deg(45.0), 0.1, 100.0);
let camera_controller = camera::CameraController::new(4.0, 0.4);
let mut camera_uniform = CameraUniform::new();
@ -306,7 +305,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -336,14 +335,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -383,14 +382,14 @@ impl State {
let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -411,7 +410,7 @@ impl State {
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -427,13 +426,12 @@ impl State {
let render_pipeline = {
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Normal Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
};
create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
shader,
@ -448,13 +446,12 @@ impl State {
});
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Light Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()),
};
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
shader,
@ -495,8 +492,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
obj_model,
camera,
@ -525,14 +521,11 @@ impl State {
if new_size.width > 0 && new_size.height > 0 {
self.projection.resize(new_size.width, new_size.height);
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -589,8 +582,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -602,7 +598,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -699,10 +695,10 @@ fn main() {
state.update(dt);
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -26,7 +26,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -256,12 +256,12 @@ impl Model {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -27,12 +27,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -42,7 +42,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -86,7 +86,7 @@ impl Texture {
is_normal_map: bool,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -104,11 +104,12 @@ impl Texture {
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -14,7 +14,7 @@ image = "0.23"
log = "0.4"
rayon = "1.4" # NEW!
tobj = "3.0"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
[build-dependencies]

@ -70,7 +70,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -129,8 +129,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
camera: camera::Camera,
@ -180,7 +179,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -216,7 +215,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -237,22 +236,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -262,7 +261,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -272,7 +271,7 @@ impl State {
// normal map
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -282,7 +281,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -296,7 +295,7 @@ impl State {
// UPDATED!
let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
let projection =
camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
camera::Projection::new(config.width, config.height, cgmath::Deg(45.0), 0.1, 100.0);
let camera_controller = camera::CameraController::new(4.0, 0.4);
let mut camera_uniform = CameraUniform::new();
@ -305,7 +304,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -337,14 +336,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -382,14 +381,14 @@ impl State {
let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -410,7 +409,7 @@ impl State {
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -426,13 +425,12 @@ impl State {
let render_pipeline = {
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Normal Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
};
create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
shader,
@ -447,13 +445,12 @@ impl State {
});
let shader = wgpu::ShaderModuleDescriptor {
label: Some("Light Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()),
};
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
shader,
@ -494,8 +491,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
obj_model,
camera,
@ -522,14 +518,11 @@ impl State {
if new_size.width > 0 && new_size.height > 0 {
self.projection.resize(new_size.width, new_size.height);
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -584,8 +577,11 @@ impl State {
);
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self.swap_chain.get_current_frame()?.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
@ -597,7 +593,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -692,10 +688,10 @@ fn main() {
state.update(dt);
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}

@ -26,7 +26,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -256,12 +256,12 @@ impl Model {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -27,12 +27,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -42,7 +42,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -86,7 +86,7 @@ impl Texture {
is_normal_map: bool,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -104,11 +104,12 @@ impl Texture {
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -14,7 +14,7 @@ image = "0.23"
log = "0.4"
rayon = "1.4"
tobj = "2.0"
wgpu = { version = "0.9", features = ["trace"] }
wgpu = { version = "0.10", features = ["trace", "spirv"] }
winit = "0.25"
[build-dependencies]
@ -22,4 +22,4 @@ anyhow = "1.0"
fs_extra = "1.2"
glob = "0.3"
rayon = "1.4"
shaderc = "0.7"
naga = { version = "0.6", features = ["glsl-in", "spv-out", "wgsl-out"]}

@ -2,42 +2,62 @@ use anyhow::*;
use fs_extra::copy_items;
use fs_extra::dir::CopyOptions;
use glob::glob;
use naga::back::wgsl;
use naga::front::glsl::Options;
use naga::front::glsl::Parser;
use rayon::prelude::*;
use std::env;
use std::fs::{read_to_string, write};
use std::path::PathBuf;
use std::{fs::read_to_string, path::PathBuf};
struct ShaderData {
src: String,
src_path: PathBuf,
spv_path: PathBuf,
kind: shaderc::ShaderKind,
}
pub fn load_shader(src_path: PathBuf) -> Result<()> {
let extension = src_path
.extension()
.context("File has no extension")?
.to_str()
.context("Extension cannot be converted to &str")?;
let kind = match extension {
"vert" => naga::ShaderStage::Vertex,
"frag" => naga::ShaderStage::Fragment,
"comp" => naga::ShaderStage::Compute,
_ => bail!("Unsupported shader: {}", src_path.display()),
};
let src = read_to_string(src_path.clone())?;
// let spv_path = src_path.with_extension(format!("{}.spv", extension));
let wgsl_path = src_path.with_extension(format!("{}.wgsl", extension));
impl ShaderData {
pub fn load(src_path: PathBuf) -> Result<Self> {
let extension = src_path
.extension()
.context("File has no extension")?
.to_str()
.context("Extension cannot be converted to &str")?;
let kind = match extension {
"vert" => shaderc::ShaderKind::Vertex,
"frag" => shaderc::ShaderKind::Fragment,
"comp" => shaderc::ShaderKind::Compute,
_ => bail!("Unsupported shader: {}", src_path.display()),
};
let mut parser = Parser::default();
let options = Options::from(kind);
let module = match parser.parse(&options, &src) {
Ok(it) => it,
Err(errors) => {
bail!(
"Failed to compile shader: {}\nErrors:\n{:#?}",
src_path.display(),
errors
);
}
};
let src = read_to_string(src_path.clone())?;
let spv_path = src_path.with_extension(format!("{}.spv", extension));
let info = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::empty(),
)
.validate(&module)?;
std::fs::write(wgsl_path, wgsl::write_string(&module, &info)?)?;
Ok(Self {
src,
src_path,
spv_path,
kind,
})
}
// let flags = spv::WriterFlags::DEBUG | spv::WriterFlags::ADJUST_COORDINATE_SPACE;
// let options = spv::Options {
// flags,
// ..Default::default()
// };
// let spv = spv::write_vec(&module, &info, &options)?;
// let dis = rspirv::dr::load_words(spv)
// .expect("Unable to disassemble shader")
// .disassemble();
// std::fs::write(spv_path, &spv)?;
Ok(())
}
fn main() -> Result<()> {
@ -46,45 +66,30 @@ fn main() -> Result<()> {
// Collect all shaders recursively within /src/
// UDPATED!
let mut shader_paths = Vec::new();
shader_paths.extend(glob("./src/**/*.vert")?);
shader_paths.extend(glob("./src/**/*.frag")?);
shader_paths.extend(glob("./src/**/*.comp")?);
let shader_paths = {
let mut data = Vec::new();
data.extend(glob("./src/**/*.vert")?);
data.extend(glob("./src/**/*.frag")?);
data.extend(glob("./src/**/*.comp")?);
data
};
// UPDATED!
// This is parallelized
let shaders = shader_paths
shader_paths
.into_par_iter()
.map(|glob_result| ShaderData::load(glob_result?))
.map(|glob_result| load_shader(glob_result?))
.collect::<Vec<Result<_>>>()
.into_iter()
.collect::<Result<Vec<_>>>();
let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?;
// This can't be parallelized. The [shaderc::Compiler] is not
// thread safe. Also, it creates a lot of resources. You could
// spawn multiple processes to handle this, but it would probably
// be better just to only compile shaders that have been changed
// recently.
for shader in shaders? {
let compiled = compiler.compile_into_spirv(
&shader.src,
shader.kind,
shader.src_path.to_str().unwrap(),
"main",
None,
)?;
write(shader.spv_path, compiled.as_binary_u8())?;
}
.collect::<Result<Vec<_>>>()?;
// This tells cargo to rerun this script if something in /res/ changes.
println!("cargo:rerun-if-changed=res/*");
let out_dir = env::var("OUT_DIR")?;
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
copy_options.overwrite = true;
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;

@ -0,0 +1,20 @@
struct FragmentOutput {
[[location(0)]] f_color: vec4<f32>;
};
var<private> v_color1: vec3<f32>;
var<private> f_color: vec4<f32>;
fn main1() {
let _e2: vec3<f32> = v_color1;
f_color = vec4<f32>(_e2, 1.0);
return;
}
[[stage(fragment)]]
fn main([[location(0)]] v_color: vec3<f32>) -> FragmentOutput {
v_color1 = v_color;
main1();
let _e7: vec4<f32> = f_color;
return FragmentOutput(_e7);
}

@ -0,0 +1,49 @@
[[block]]
struct Camera {
u_view_position: vec3<f32>;
u_view_proj: mat4x4<f32>;
};
[[block]]
struct Light {
u_position: vec3<f32>;
u_color: vec3<f32>;
};
struct VertexOutput {
[[location(0)]] v_color: vec3<f32>;
[[builtin(position)]] member: vec4<f32>;
};
var<private> a_position1: vec3<f32>;
var<private> v_color: vec3<f32>;
[[group(0), binding(0)]]
var<uniform> global: Camera;
[[group(1), binding(0)]]
var<uniform> global1: Light;
var<private> scale: f32 = 0.25;
var<private> gl_Position: vec4<f32>;
fn main1() {
var v_position: vec3<f32>;
let _e11: vec3<f32> = a_position1;
let _e12: f32 = scale;
let _e14: vec3<f32> = global1.u_position;
v_position = ((_e11 * _e12) + _e14);
let _e18: mat4x4<f32> = global.u_view_proj;
let _e19: vec3<f32> = v_position;
gl_Position = (_e18 * vec4<f32>(_e19, f32(1)));
let _e24: vec3<f32> = global1.u_color;
v_color = _e24;
return;
}
[[stage(vertex)]]
fn main([[location(0)]] a_position: vec3<f32>) -> VertexOutput {
a_position1 = a_position;
main1();
let _e18: vec3<f32> = v_color;
let _e20: vec4<f32> = gl_Position;
return VertexOutput(_e18, _e20);
}

@ -52,15 +52,17 @@ impl Instance {
model: (cgmath::Matrix4::from_translation(self.position)
* cgmath::Matrix4::from(self.rotation))
.into(),
normal: cgmath::Matrix3::from(self.rotation).into(),
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[allow(dead_code)]
struct InstanceRaw {
#[allow(dead_code)]
model: [[f32; 4]; 4],
normal: [[f32; 3]; 3],
}
impl model::Vertex for InstanceRaw {
@ -71,7 +73,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -97,6 +99,21 @@ impl model::Vertex for InstanceRaw {
shader_location: 8,
format: wgpu::VertexFormat::Float32x4,
},
wgpu::VertexAttribute {
offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress,
shader_location: 9,
format: wgpu::VertexFormat::Float32x3,
},
wgpu::VertexAttribute {
offset: mem::size_of::<[f32; 19]>() as wgpu::BufferAddress,
shader_location: 10,
format: wgpu::VertexFormat::Float32x3,
},
wgpu::VertexAttribute {
offset: mem::size_of::<[f32; 22]>() as wgpu::BufferAddress,
shader_location: 11,
format: wgpu::VertexFormat::Float32x3,
},
],
}
}
@ -115,8 +132,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
obj_model: model::Model,
camera: camera::Camera,
@ -146,7 +162,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -168,22 +184,22 @@ impl State {
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let texture_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -193,7 +209,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -203,7 +219,7 @@ impl State {
// normal map
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -213,7 +229,7 @@ impl State {
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -227,7 +243,7 @@ impl State {
// UPDATED!
let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
let projection =
camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
camera::Projection::new(config.width, config.height, cgmath::Deg(45.0), 0.1, 100.0);
let camera_controller = camera::CameraController::new(4.0, 0.4);
let mut camera_uniform = CameraUniform::new();
@ -236,7 +252,7 @@ impl State {
let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
const SPACE_BETWEEN: f32 = 3.0;
@ -268,14 +284,14 @@ impl State {
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -317,14 +333,14 @@ impl State {
let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -345,7 +361,7 @@ impl State {
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
texture::Texture::create_depth_texture(&device, &config, "depth_texture");
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -358,16 +374,18 @@ impl State {
push_constant_ranges: &[],
});
println!("Creating RENDER pipeline");
let render_pipeline = create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
wgpu::include_spirv!("shader.vert.spv"),
wgpu::include_spirv!("shader.frag.spv"),
wgpu::include_wgsl!("shader.vert.wgsl"),
wgpu::include_wgsl!("shader.frag.wgsl"),
);
println!("Creating LIGHT pipeline");
let light_render_pipeline = {
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Light Pipeline Layout"),
@ -378,11 +396,11 @@ impl State {
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
wgpu::include_spirv!("light.vert.spv"),
wgpu::include_spirv!("light.frag.spv"),
wgpu::include_wgsl!("light.vert.wgsl"),
wgpu::include_wgsl!("light.frag.wgsl"),
)
};
@ -420,8 +438,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
obj_model,
camera,
@ -449,14 +466,11 @@ impl State {
if new_size.width > 0 && new_size.height > 0 {
self.projection.resize(new_size.width, new_size.height);
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.depth_texture = texture::Texture::create_depth_texture(
&self.device,
&self.sc_desc,
"depth_texture",
);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
}
}
@ -520,11 +534,14 @@ impl State {
}
fn render(&mut self) {
let frame = self.swap_chain.get_current_frame();
let frame = self.surface.get_current_frame();
match frame {
Ok(frame) => {
let frame = frame.output;
let output = frame.output;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder =
self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
@ -535,7 +552,7 @@ impl State {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {

@ -27,7 +27,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -141,7 +141,7 @@ impl pipeline::Bindable for BitangentComputeBinding {
// We use these vertices to compute the tangent and bitangent
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::COMPUTE,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
@ -153,7 +153,7 @@ impl pipeline::Bindable for BitangentComputeBinding {
// We'll store the computed tangent and bitangent here
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::COMPUTE,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage {
// We will change the values in this buffer
@ -167,7 +167,7 @@ impl pipeline::Bindable for BitangentComputeBinding {
// Indices
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::COMPUTE,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage {
// We won't change the indices
@ -181,7 +181,7 @@ impl pipeline::Bindable for BitangentComputeBinding {
// ComputeInfo
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::COMPUTE,
visibility: wgpu::ShaderStages::COMPUTE,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -232,8 +232,9 @@ pub struct ModelLoader {
impl ModelLoader {
// NEW!
pub fn new(device: &wgpu::Device) -> Self {
println!("Creating MODELLOADER pipeline");
let binder = pipeline::Binder::new(device, Some("ModelLoader Binder"));
let shader_src = wgpu::include_spirv!("model_load.comp.spv");
let shader_src = wgpu::include_wgsl!("model_load.comp.wgsl");
let pipeline = pipeline::create_compute_pipeline(
device,
&[&binder.layout],
@ -316,20 +317,20 @@ impl ModelLoader {
label: Some(&format!("{:?} Vertex Buffer", m.name)),
contents: bytemuck::cast_slice(&vertices),
// UPDATED!
usage: wgpu::BufferUsage::STORAGE,
usage: wgpu::BufferUsages::STORAGE,
});
let dst_vertex_buffer =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", m.name)),
contents: bytemuck::cast_slice(&vertices),
// UPDATED!
usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::STORAGE,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::STORAGE,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", m.name)),
contents: bytemuck::cast_slice(&m.mesh.indices),
// UPDATED!
usage: wgpu::BufferUsage::INDEX | wgpu::BufferUsage::STORAGE,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::STORAGE,
});
let compute_info = ComputeInfo {
num_vertices: vertices.len() as _,
@ -338,7 +339,7 @@ impl ModelLoader {
let info_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Compute Info Buffer", m.name)),
contents: bytemuck::cast_slice(&[compute_info]),
usage: wgpu::BufferUsage::UNIFORM,
usage: wgpu::BufferUsages::UNIFORM,
});
// NEW!

@ -11,13 +11,13 @@ struct ModelVertex {
uint pad0; uint pad1;
};
layout(std430, set=0, binding=0) buffer SrcVertexBuffer {
layout(std430, set=0, binding=0) readonly buffer SrcVertexBuffer {
ModelVertex srcVertices[];
};
layout(std430, set=0, binding=1) buffer DstVertexBuffer {
ModelVertex dstVertices[];
};
layout(std430, set=0, binding=2) buffer IndexBuffer {
layout(std430, set=0, binding=2) readonly buffer IndexBuffer {
uint indices[];
};

@ -0,0 +1,252 @@
struct ModelVertex {
x: f32;
y: f32;
z: f32;
uv: f32;
uw: f32;
nx: f32;
ny: f32;
nz: f32;
tx: f32;
ty: f32;
tz: f32;
bx: f32;
by: f32;
bz: f32;
pad0_: u32;
pad1_: u32;
};
[[block]]
struct SrcVertexBuffer {
srcVertices: [[stride(64)]] array<ModelVertex>;
};
[[block]]
struct DstVertexBuffer {
dstVertices: [[stride(64)]] array<ModelVertex>;
};
[[block]]
struct IndexBuffer {
indices: [[stride(4)]] array<u32>;
};
[[block]]
struct ComputeInfo {
numVertices: u32;
numIndices: u32;
};
[[group(0), binding(0)]]
var<storage> global: SrcVertexBuffer;
[[group(0), binding(1)]]
var<storage, read_write> global1: DstVertexBuffer;
[[group(0), binding(2)]]
var<storage> global2: IndexBuffer;
[[group(0), binding(3)]]
var<uniform> global3: ComputeInfo;
var<private> gl_GlobalInvocationID: vec3<u32>;
fn getPos(v: ModelVertex) -> vec3<f32> {
var v1: ModelVertex;
v1 = v;
let _e12: ModelVertex = v1;
let _e14: ModelVertex = v1;
let _e16: ModelVertex = v1;
return vec3<f32>(_e12.x, _e14.y, _e16.z);
}
fn getUV(v2: ModelVertex) -> vec2<f32> {
var v3: ModelVertex;
v3 = v2;
let _e12: ModelVertex = v3;
let _e14: ModelVertex = v3;
return vec2<f32>(_e12.uv, _e14.uw);
}
fn getNormal(v4: ModelVertex) -> vec3<f32> {
var v5: ModelVertex;
v5 = v4;
let _e12: ModelVertex = v5;
let _e14: ModelVertex = v5;
let _e16: ModelVertex = v5;
return vec3<f32>(_e12.nx, _e14.ny, _e16.nz);
}
fn calcTangentBitangent(vertexIndex: u32) -> ModelVertex {
var vertexIndex1: u32;
var v6: ModelVertex;
var tangent: vec3<f32> = vec3<f32>(0.0, 0.0, 0.0);
var bitangent: vec3<f32> = vec3<f32>(0.0, 0.0, 0.0);
var trianglesIncluded: u32 = 0u;
var i: u32 = 0u;
var index0_: u32;
var index1_: u32;
var index2_: u32;
var v0_: ModelVertex;
var v1_: ModelVertex;
var v2_: ModelVertex;
var pos0_: vec3<f32>;
var pos1_: vec3<f32>;
var pos2_: vec3<f32>;
var uv0_: vec2<f32>;
var uv1_: vec2<f32>;
var uv2_: vec2<f32>;
var delta_pos1_: vec3<f32>;
var delta_pos2_: vec3<f32>;
var delta_uv1_: vec2<f32>;
var delta_uv2_: vec2<f32>;
var r: f32;
vertexIndex1 = vertexIndex;
let _e12: u32 = vertexIndex1;
let _e14: ModelVertex = global.srcVertices[_e12];
v6 = _e14;
loop {
let _e30: u32 = i;
let _e31: u32 = global3.numIndices;
if (!((_e30 < _e31))) {
break;
}
{
let _e38: u32 = i;
let _e40: u32 = global2.indices[_e38];
index0_ = _e40;
let _e42: u32 = i;
let _e47: u32 = global2.indices[(_e42 + u32(1))];
index1_ = _e47;
let _e49: u32 = i;
let _e54: u32 = global2.indices[(_e49 + u32(2))];
index2_ = _e54;
let _e56: u32 = index0_;
let _e57: u32 = vertexIndex1;
let _e59: u32 = index1_;
let _e60: u32 = vertexIndex1;
let _e63: u32 = index2_;
let _e64: u32 = vertexIndex1;
if ((((_e56 == _e57) || (_e59 == _e60)) || (_e63 == _e64))) {
{
let _e67: u32 = index0_;
let _e69: ModelVertex = global.srcVertices[_e67];
v0_ = _e69;
let _e71: u32 = index1_;
let _e73: ModelVertex = global.srcVertices[_e71];
v1_ = _e73;
let _e75: u32 = index2_;
let _e77: ModelVertex = global.srcVertices[_e75];
v2_ = _e77;
let _e80: ModelVertex = v0_;
let _e81: vec3<f32> = getPos(_e80);
pos0_ = _e81;
let _e84: ModelVertex = v1_;
let _e85: vec3<f32> = getPos(_e84);
pos1_ = _e85;
let _e88: ModelVertex = v2_;
let _e89: vec3<f32> = getPos(_e88);
pos2_ = _e89;
let _e92: ModelVertex = v0_;
let _e93: vec2<f32> = getUV(_e92);
uv0_ = _e93;
let _e96: ModelVertex = v1_;
let _e97: vec2<f32> = getUV(_e96);
uv1_ = _e97;
let _e100: ModelVertex = v2_;
let _e101: vec2<f32> = getUV(_e100);
uv2_ = _e101;
let _e103: vec3<f32> = pos1_;
let _e104: vec3<f32> = pos0_;
delta_pos1_ = (_e103 - _e104);
let _e107: vec3<f32> = pos2_;
let _e108: vec3<f32> = pos0_;
delta_pos2_ = (_e107 - _e108);
let _e111: vec2<f32> = uv1_;
let _e112: vec2<f32> = uv0_;
delta_uv1_ = (_e111 - _e112);
let _e115: vec2<f32> = uv2_;
let _e116: vec2<f32> = uv0_;
delta_uv2_ = (_e115 - _e116);
let _e120: vec2<f32> = delta_uv1_;
let _e122: vec2<f32> = delta_uv2_;
let _e125: vec2<f32> = delta_uv1_;
let _e127: vec2<f32> = delta_uv2_;
r = (1.0 / ((_e120.x * _e122.y) - (_e125.y * _e127.x)));
let _e133: vec3<f32> = tangent;
let _e134: vec3<f32> = delta_pos1_;
let _e135: vec2<f32> = delta_uv2_;
let _e138: vec3<f32> = delta_pos2_;
let _e139: vec2<f32> = delta_uv1_;
let _e143: f32 = r;
tangent = (_e133 + (((_e134 * _e135.y) - (_e138 * _e139.y)) * _e143));
let _e146: vec3<f32> = bitangent;
let _e147: vec3<f32> = delta_pos2_;
let _e148: vec2<f32> = delta_uv1_;
let _e151: vec3<f32> = delta_pos1_;
let _e152: vec2<f32> = delta_uv2_;
let _e156: f32 = r;
bitangent = (_e146 + (((_e147 * _e148.x) - (_e151 * _e152.x)) * _e156));
let _e159: u32 = trianglesIncluded;
trianglesIncluded = (_e159 + u32(1));
}
}
}
continuing {
let _e34: u32 = i;
i = (_e34 + u32(3));
}
}
let _e163: u32 = trianglesIncluded;
if ((_e163 > u32(0))) {
{
let _e167: vec3<f32> = tangent;
let _e168: u32 = trianglesIncluded;
tangent = (_e167 / vec3<f32>(f32(_e168)));
let _e172: vec3<f32> = bitangent;
let _e173: u32 = trianglesIncluded;
bitangent = (_e172 / vec3<f32>(f32(_e173)));
let _e178: vec3<f32> = tangent;
tangent = normalize(_e178);
let _e181: vec3<f32> = bitangent;
bitangent = normalize(_e181);
}
}
let _e184: vec3<f32> = tangent;
v6.tx = _e184.x;
let _e187: vec3<f32> = tangent;
v6.ty = _e187.y;
let _e190: vec3<f32> = tangent;
v6.tz = _e190.z;
let _e193: vec3<f32> = bitangent;
v6.bx = _e193.x;
let _e196: vec3<f32> = bitangent;
v6.by = _e196.y;
let _e199: vec3<f32> = bitangent;
v6.bz = _e199.z;
let _e201: ModelVertex = v6;
return _e201;
}
fn main1() {
var vertexIndex2: u32;
var result: ModelVertex;
let _e11: vec3<u32> = gl_GlobalInvocationID;
vertexIndex2 = _e11.x;
let _e15: u32 = vertexIndex2;
let _e16: ModelVertex = calcTangentBitangent(_e15);
result = _e16;
let _e18: u32 = vertexIndex2;
let _e20: ModelVertex = result;
global1.dstVertices[_e18] = _e20;
return;
}
[[stage(compute), workgroup_size(64, 1, 1)]]
fn main([[builtin(global_invocation_id)]] param: vec3<u32>) {
gl_GlobalInvocationID = param;
main1();
return;
}

@ -40,12 +40,12 @@ pub fn create_render_pipeline(
color_format: wgpu::TextureFormat,
depth_format: Option<wgpu::TextureFormat>,
vertex_layouts: &[wgpu::VertexBufferLayout],
mut vs_src: wgpu::ShaderModuleDescriptor,
mut fs_src: wgpu::ShaderModuleDescriptor,
vs_src: wgpu::ShaderModuleDescriptor,
fs_src: wgpu::ShaderModuleDescriptor,
) -> wgpu::RenderPipeline {
vs_src.flags &= wgpu::ShaderFlags::VALIDATION;
fs_src.flags &= wgpu::ShaderFlags::VALIDATION;
println!("Creating VS Module =======");
let vs_module = device.create_shader_module(&vs_src);
println!("Creating FS Module =======");
let fs_module = device.create_shader_module(&fs_src);
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
@ -62,7 +62,7 @@ pub fn create_render_pipeline(
targets: &[wgpu::ColorTargetState {
format: color_format,
blend: None,
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {

@ -0,0 +1,109 @@
[[block]]
struct Light {
light_position: vec3<f32>;
light_color: vec3<f32>;
};
struct FragmentOutput {
[[location(0)]] f_color: vec4<f32>;
};
var<private> v_tex_coords1: vec2<f32>;
var<private> v_position1: vec3<f32>;
var<private> v_light_position1: vec3<f32>;
var<private> v_view_position1: vec3<f32>;
var<private> f_color: vec4<f32>;
[[group(0), binding(0)]]
var t_diffuse: texture_2d<f32>;
[[group(0), binding(1)]]
var s_diffuse: sampler;
[[group(0), binding(2)]]
var t_normal: texture_2d<f32>;
[[group(0), binding(3)]]
var s_normal: sampler;
[[group(2), binding(0)]]
var<uniform> global: Light;
fn main1() {
var object_color: vec4<f32>;
var object_normal: vec4<f32>;
var ambient_strength: f32 = 0.10000000149011612;
var ambient_color: vec3<f32>;
var normal: vec3<f32>;
var light_dir: vec3<f32>;
var diffuse_strength: f32;
var diffuse_color: vec3<f32>;
var view_dir: vec3<f32>;
var half_dir: vec3<f32>;
var specular_strength: f32;
var specular_color: vec3<f32>;
var result: vec3<f32>;
let _e14: vec2<f32> = v_tex_coords1;
let _e15: vec4<f32> = textureSample(t_diffuse, s_diffuse, _e14);
object_color = _e15;
let _e18: vec2<f32> = v_tex_coords1;
let _e19: vec4<f32> = textureSample(t_normal, s_normal, _e18);
object_normal = _e19;
let _e23: vec3<f32> = global.light_color;
let _e24: f32 = ambient_strength;
ambient_color = (_e23 * _e24);
let _e27: vec4<f32> = object_normal;
let _e34: vec4<f32> = object_normal;
normal = normalize(((_e34.xyz * 2.0) - vec3<f32>(1.0)));
let _e43: vec3<f32> = v_light_position1;
let _e44: vec3<f32> = v_position1;
let _e46: vec3<f32> = v_light_position1;
let _e47: vec3<f32> = v_position1;
light_dir = normalize((_e46 - _e47));
let _e53: vec3<f32> = normal;
let _e54: vec3<f32> = light_dir;
let _e59: vec3<f32> = normal;
let _e60: vec3<f32> = light_dir;
diffuse_strength = max(dot(_e59, _e60), 0.0);
let _e65: vec3<f32> = global.light_color;
let _e66: f32 = diffuse_strength;
diffuse_color = (_e65 * _e66);
let _e69: vec3<f32> = v_view_position1;
let _e70: vec3<f32> = v_position1;
let _e72: vec3<f32> = v_view_position1;
let _e73: vec3<f32> = v_position1;
view_dir = normalize((_e72 - _e73));
let _e77: vec3<f32> = view_dir;
let _e78: vec3<f32> = light_dir;
let _e80: vec3<f32> = view_dir;
let _e81: vec3<f32> = light_dir;
half_dir = normalize((_e80 + _e81));
let _e87: vec3<f32> = normal;
let _e88: vec3<f32> = half_dir;
let _e93: vec3<f32> = normal;
let _e94: vec3<f32> = half_dir;
let _e101: vec3<f32> = normal;
let _e102: vec3<f32> = half_dir;
let _e107: vec3<f32> = normal;
let _e108: vec3<f32> = half_dir;
specular_strength = pow(max(dot(_e107, _e108), 0.0), f32(32));
let _e116: f32 = specular_strength;
let _e117: vec3<f32> = global.light_color;
specular_color = (_e116 * _e117);
let _e120: vec3<f32> = ambient_color;
let _e121: vec3<f32> = diffuse_color;
let _e123: vec3<f32> = specular_color;
let _e125: vec4<f32> = object_color;
result = (((_e120 + _e121) + _e123) * _e125.xyz);
let _e129: vec3<f32> = result;
let _e130: vec4<f32> = object_color;
f_color = vec4<f32>(_e129, _e130.w);
return;
}
[[stage(fragment)]]
fn main([[location(0)]] v_tex_coords: vec2<f32>, [[location(1)]] v_position: vec3<f32>, [[location(2)]] v_light_position: vec3<f32>, [[location(3)]] v_view_position: vec3<f32>) -> FragmentOutput {
v_tex_coords1 = v_tex_coords;
v_position1 = v_position;
v_light_position1 = v_light_position;
v_view_position1 = v_view_position;
main1();
let _e31: vec4<f32> = f_color;
return FragmentOutput(_e31);
}

@ -22,6 +22,10 @@ layout(location=6) in vec4 model_matrix_1;
layout(location=7) in vec4 model_matrix_2;
layout(location=8) in vec4 model_matrix_3;
layout(location=9) in vec3 normal_matrix_0;
layout(location=10) in vec3 normal_matrix_1;
layout(location=11) in vec3 normal_matrix_2;
// NEW!
layout(set=2, binding=0) uniform Light {
vec3 light_position;
@ -37,7 +41,11 @@ void main() {
);
v_tex_coords = a_tex_coords;
mat3 normal_matrix = mat3(transpose(inverse(model_matrix)));
mat3 normal_matrix = mat3(
normal_matrix_0,
normal_matrix_1,
normal_matrix_2
);
vec3 normal = normalize(normal_matrix * a_normal);
vec3 tangent = normalize(normal_matrix * a_tangent);
vec3 bitangent = normalize(normal_matrix * a_bitangent);
@ -50,7 +58,6 @@ void main() {
));
vec4 model_space = model_matrix * vec4(a_position, 1.0);
v_position = model_space.xyz;
// NEW!
v_position = tangent_matrix * model_space.xyz;

@ -0,0 +1,124 @@
[[block]]
struct Camera {
u_view_position: vec3<f32>;
u_view_proj: mat4x4<f32>;
};
[[block]]
struct Light {
light_position: vec3<f32>;
light_color: vec3<f32>;
};
struct VertexOutput {
[[location(0)]] v_tex_coords: vec2<f32>;
[[location(1)]] v_position: vec3<f32>;
[[location(2)]] v_light_position: vec3<f32>;
[[location(3)]] v_view_position: vec3<f32>;
[[builtin(position)]] member: vec4<f32>;
};
var<private> a_position1: vec3<f32>;
var<private> a_tex_coords1: vec2<f32>;
var<private> a_normal1: vec3<f32>;
var<private> a_tangent1: vec3<f32>;
var<private> a_bitangent1: vec3<f32>;
var<private> v_tex_coords: vec2<f32>;
var<private> v_position: vec3<f32>;
var<private> v_light_position: vec3<f32>;
var<private> v_view_position: vec3<f32>;
[[group(1), binding(0)]]
var<uniform> global: Camera;
var<private> model_matrix_0_1: vec4<f32>;
var<private> model_matrix_1_1: vec4<f32>;
var<private> model_matrix_2_1: vec4<f32>;
var<private> model_matrix_3_1: vec4<f32>;
var<private> normal_matrix_0_1: vec3<f32>;
var<private> normal_matrix_1_1: vec3<f32>;
var<private> normal_matrix_2_1: vec3<f32>;
[[group(2), binding(0)]]
var<uniform> global1: Light;
var<private> gl_Position: vec4<f32>;
fn main1() {
var model_matrix: mat4x4<f32>;
var normal_matrix: mat3x3<f32>;
var normal: vec3<f32>;
var tangent: vec3<f32>;
var bitangent: vec3<f32>;
var tangent_matrix: mat3x3<f32>;
var model_space: vec4<f32>;
let _e24: vec4<f32> = model_matrix_0_1;
let _e25: vec4<f32> = model_matrix_1_1;
let _e26: vec4<f32> = model_matrix_2_1;
let _e27: vec4<f32> = model_matrix_3_1;
model_matrix = mat4x4<f32>(vec4<f32>(_e24.x, _e24.y, _e24.z, _e24.w), vec4<f32>(_e25.x, _e25.y, _e25.z, _e25.w), vec4<f32>(_e26.x, _e26.y, _e26.z, _e26.w), vec4<f32>(_e27.x, _e27.y, _e27.z, _e27.w));
let _e50: vec2<f32> = a_tex_coords1;
v_tex_coords = _e50;
let _e51: vec3<f32> = normal_matrix_0_1;
let _e52: vec3<f32> = normal_matrix_1_1;
let _e53: vec3<f32> = normal_matrix_2_1;
normal_matrix = mat3x3<f32>(vec3<f32>(_e51.x, _e51.y, _e51.z), vec3<f32>(_e52.x, _e52.y, _e52.z), vec3<f32>(_e53.x, _e53.y, _e53.z));
let _e68: mat3x3<f32> = normal_matrix;
let _e69: vec3<f32> = a_normal1;
let _e71: mat3x3<f32> = normal_matrix;
let _e72: vec3<f32> = a_normal1;
normal = normalize((_e71 * _e72));
let _e76: mat3x3<f32> = normal_matrix;
let _e77: vec3<f32> = a_tangent1;
let _e79: mat3x3<f32> = normal_matrix;
let _e80: vec3<f32> = a_tangent1;
tangent = normalize((_e79 * _e80));
let _e84: mat3x3<f32> = normal_matrix;
let _e85: vec3<f32> = a_bitangent1;
let _e87: mat3x3<f32> = normal_matrix;
let _e88: vec3<f32> = a_bitangent1;
bitangent = normalize((_e87 * _e88));
let _e92: vec3<f32> = tangent;
let _e93: vec3<f32> = bitangent;
let _e94: vec3<f32> = normal;
let _e108: vec3<f32> = tangent;
let _e109: vec3<f32> = bitangent;
let _e110: vec3<f32> = normal;
tangent_matrix = transpose(mat3x3<f32>(vec3<f32>(_e108.x, _e108.y, _e108.z), vec3<f32>(_e109.x, _e109.y, _e109.z), vec3<f32>(_e110.x, _e110.y, _e110.z)));
let _e126: mat4x4<f32> = model_matrix;
let _e127: vec3<f32> = a_position1;
model_space = (_e126 * vec4<f32>(_e127, 1.0));
let _e132: mat3x3<f32> = tangent_matrix;
let _e133: vec4<f32> = model_space;
v_position = (_e132 * _e133.xyz);
let _e136: mat3x3<f32> = tangent_matrix;
let _e137: vec3<f32> = global1.light_position;
v_light_position = (_e136 * _e137);
let _e139: mat3x3<f32> = tangent_matrix;
let _e140: vec3<f32> = global.u_view_position;
v_view_position = (_e139 * _e140);
let _e143: mat4x4<f32> = global.u_view_proj;
let _e144: vec4<f32> = model_space;
gl_Position = (_e143 * _e144);
return;
}
[[stage(vertex)]]
fn main([[location(0)]] a_position: vec3<f32>, [[location(1)]] a_tex_coords: vec2<f32>, [[location(2)]] a_normal: vec3<f32>, [[location(3)]] a_tangent: vec3<f32>, [[location(4)]] a_bitangent: vec3<f32>, [[location(5)]] model_matrix_0_: vec4<f32>, [[location(6)]] model_matrix_1_: vec4<f32>, [[location(7)]] model_matrix_2_: vec4<f32>, [[location(8)]] model_matrix_3_: vec4<f32>, [[location(9)]] normal_matrix_0_: vec3<f32>, [[location(10)]] normal_matrix_1_: vec3<f32>, [[location(11)]] normal_matrix_2_: vec3<f32>) -> VertexOutput {
a_position1 = a_position;
a_tex_coords1 = a_tex_coords;
a_normal1 = a_normal;
a_tangent1 = a_tangent;
a_bitangent1 = a_bitangent;
model_matrix_0_1 = model_matrix_0_;
model_matrix_1_1 = model_matrix_1_;
model_matrix_2_1 = model_matrix_2_;
model_matrix_3_1 = model_matrix_3_;
normal_matrix_0_1 = normal_matrix_0_;
normal_matrix_1_1 = normal_matrix_1_;
normal_matrix_2_1 = normal_matrix_2_;
main1();
let _e65: vec2<f32> = v_tex_coords;
let _e67: vec3<f32> = v_position;
let _e69: vec3<f32> = v_light_position;
let _e71: vec3<f32> = v_view_position;
let _e73: vec4<f32> = gl_Position;
return VertexOutput(_e65, _e67, _e69, _e71, _e73);
}

@ -27,12 +27,12 @@ impl Texture {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -42,7 +42,7 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
@ -86,7 +86,7 @@ impl Texture {
is_normal_map: bool,
) -> Result<Self> {
let dimensions = img.dimensions();
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let size = wgpu::Extent3d {
width: dimensions.0,
@ -104,11 +104,12 @@ impl Texture {
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -14,7 +14,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "2.0"
wgpu = "0.9"
wgpu = "0.10"
wgpu-subscriber = "0.1"
winit = "0.25"

@ -18,13 +18,13 @@ impl<R: Copy + bytemuck::Pod + bytemuck::Zeroable> RawBuffer<R> {
pub fn from_slice<T: ToRaw<Output = R>>(
device: &wgpu::Device,
data: &[T],
usage: wgpu::BufferUsage,
usage: wgpu::BufferUsages,
) -> Self {
let raw_data = data.iter().map(ToRaw::to_raw).collect::<Vec<R>>();
Self::from_vec(device, raw_data, usage)
}
pub fn from_vec(device: &wgpu::Device, data: Vec<R>, usage: wgpu::BufferUsage) -> Self {
pub fn from_vec(device: &wgpu::Device, data: Vec<R>, usage: wgpu::BufferUsages) -> Self {
let buffer = device.create_buffer_init(&BufferInitDescriptor {
contents: bytemuck::cast_slice(&data),
usage,
@ -33,7 +33,7 @@ impl<R: Copy + bytemuck::Pod + bytemuck::Zeroable> RawBuffer<R> {
Self::from_parts(buffer, data, usage)
}
pub fn from_parts(buffer: wgpu::Buffer, data: Vec<R>, _usage: wgpu::BufferUsage) -> Self {
pub fn from_parts(buffer: wgpu::Buffer, data: Vec<R>, _usage: wgpu::BufferUsages) -> Self {
Self { buffer, data }
}
@ -45,26 +45,26 @@ impl<R: Copy + bytemuck::Pod + bytemuck::Zeroable> RawBuffer<R> {
pub struct Buffer<U: ToRaw<Output = R>, R: Copy + bytemuck::Pod + bytemuck::Zeroable> {
pub data: Vec<U>,
pub raw_buffer: RawBuffer<R>,
pub usage: wgpu::BufferUsage,
pub usage: wgpu::BufferUsages,
}
impl<U: ToRaw<Output = R>, R: Copy + bytemuck::Pod + bytemuck::Zeroable> Buffer<U, R> {
pub fn uniform(device: &wgpu::Device, datum: U) -> Self {
let data = vec![datum];
let usage = wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST;
let usage = wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST;
Self::with_usage(device, data, usage)
}
pub fn storage(device: &wgpu::Device, data: Vec<U>) -> Self {
let usage = wgpu::BufferUsage::STORAGE | wgpu::BufferUsage::COPY_DST;
let usage = wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST;
Self::with_usage(device, data, usage)
}
pub fn staging(device: &wgpu::Device, other: &Self) -> Self {
let buffer_size = other.raw_buffer.buffer_size();
let usage = wgpu::BufferUsage::COPY_SRC
| wgpu::BufferUsage::MAP_READ
| wgpu::BufferUsage::MAP_WRITE;
let usage = wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::MAP_READ
| wgpu::BufferUsages::MAP_WRITE;
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
size: buffer_size,
usage,
@ -75,12 +75,12 @@ impl<U: ToRaw<Output = R>, R: Copy + bytemuck::Pod + bytemuck::Zeroable> Buffer<
Self::from_parts(Vec::new(), raw_buffer, usage)
}
pub fn with_usage(device: &wgpu::Device, data: Vec<U>, usage: wgpu::BufferUsage) -> Self {
pub fn with_usage(device: &wgpu::Device, data: Vec<U>, usage: wgpu::BufferUsages) -> Self {
let raw_buffer = RawBuffer::from_slice(device, &data, usage);
Self::from_parts(data, raw_buffer, usage)
}
pub fn from_parts(data: Vec<U>, raw_buffer: RawBuffer<R>, usage: wgpu::BufferUsage) -> Self {
pub fn from_parts(data: Vec<U>, raw_buffer: RawBuffer<R>, usage: wgpu::BufferUsages) -> Self {
Self {
data,
raw_buffer,

@ -26,8 +26,7 @@ use winit::window::{Window, WindowBuilder};
pub struct Display {
surface: wgpu::Surface,
pub window: Window,
pub sc_desc: wgpu::SwapChainDescriptor,
pub swap_chain: wgpu::SwapChain,
pub config: wgpu::SurfaceConfiguration,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
}
@ -35,7 +34,7 @@ pub struct Display {
impl Display {
pub async fn new(window: Window) -> Result<Self, Error> {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(&window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -55,29 +54,28 @@ impl Display {
)
.await
.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
Ok(Self {
surface,
window,
sc_desc,
swap_chain,
config,
device,
queue,
})
}
pub fn resize(&mut self, width: u32, height: u32) {
self.sc_desc.width = width;
self.sc_desc.height = height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = width;
self.config.height = height;
self.surface.configure(&self.device, &self.config);
}
}
@ -108,7 +106,7 @@ impl CameraUniform {
let buffer = device.create_buffer_init(&BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM,
});
Self { data, buffer }
@ -123,7 +121,7 @@ impl CameraUniform {
let staging_buffer = device.create_buffer_init(&BufferInitDescriptor {
label: Some("Camera Update Buffer"),
contents: bytemuck::cast_slice(&[self.data]),
usage: wgpu::BufferUsage::COPY_SRC,
usage: wgpu::BufferUsages::COPY_SRC,
});
encoder.copy_buffer_to_buffer(
&staging_buffer,
@ -149,7 +147,7 @@ impl UniformBinding {
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,

@ -26,7 +26,7 @@ impl LightUniform {
};
let buffer = device.create_buffer_init(&BufferInitDescriptor {
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM,
label: Some("Light Buffer"),
});

@ -24,7 +24,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -222,12 +222,12 @@ impl<'a> Model<'a> {
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
});
meshes.push(Mesh {

@ -103,7 +103,7 @@ impl<'a> RenderPipelineBuilder<'a> {
self.color_state(wgpu::ColorTargetState {
format,
blend: None,
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
})
}

@ -127,9 +127,9 @@ impl<'a> ShaderCanvasBuilder<'a> {
self
}
pub fn use_swap_chain_desc(&mut self, sc_desc: &wgpu::SwapChainDescriptor) -> &mut Self {
self.display_format(sc_desc.format);
self.canvas_size(sc_desc.width as f32, sc_desc.height as f32)
pub fn use_swap_chain_desc(&mut self, config: &wgpu::SurfaceConfiguration) -> &mut Self {
self.display_format(config.format);
self.canvas_size(config.width as f32, config.height as f32)
}
pub fn fragment_shader(&mut self, code: wgpu::ShaderModuleDescriptor<'a>) -> &mut Self {
@ -165,7 +165,7 @@ impl<'a> ShaderCanvasBuilder<'a> {
let simulation_data_buffer = device.create_buffer_init(&BufferInitDescriptor {
label: self.label,
contents: bytemuck::cast_slice(&[simulation_data]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let simulation_bind_group_layout =
@ -175,7 +175,7 @@ impl<'a> ShaderCanvasBuilder<'a> {
// SimulationData
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
count: None,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
@ -219,7 +219,7 @@ impl<'a> ShaderCanvasBuilder<'a> {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {

@ -70,7 +70,7 @@ impl<'a> Texture<'a> {
_label: Option<&str>,
is_normal_map: bool,
) -> Result<Self> {
let rgba = img.to_rgba();
let rgba = img.to_rgba8();
let dimensions = img.dimensions();
let size = wgpu::Extent3d {
@ -88,13 +88,14 @@ impl<'a> Texture<'a> {
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: None,
};
let texture = device.create_texture(&desc);
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
@ -132,20 +133,20 @@ impl<'a> Texture<'a> {
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
config: &wgpu::SurfaceConfiguration,
) -> Self {
let desc = wgpu::TextureDescriptor {
label: None,
size: wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
};
Self::from_descriptor(device, desc)
}
@ -155,7 +156,7 @@ impl<'a> Texture<'a> {
self.desc.size.width * self.desc.size.height * self.desc.size.depth_or_array_layers;
let buffer_size = num_pixels * mem::size_of::<[f32; 4]>() as u32;
let buffer_usage = wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::MAP_READ;
let buffer_usage = wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ;
let buffer_desc = wgpu::BufferDescriptor {
size: buffer_size as wgpu::BufferAddress,
usage: buffer_usage,

@ -14,7 +14,7 @@ pollster = "0.2"
image = "0.23"
log = "0.4"
tobj = "3.1"
wgpu = "0.9"
wgpu = "0.10"
winit = "0.25"
gif = "0.10.3"

@ -4,7 +4,7 @@ use anyhow::*;
use std::{iter, mem, num::NonZeroU32};
async fn run() {
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions::default())
.await
@ -44,7 +44,7 @@ async fn run() {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_SRC | wgpu::TextureUsage::RENDER_ATTACHMENT,
usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT,
label: None,
};
let render_target = framework::Texture::from_descriptor(&device, rt_desc);
@ -63,7 +63,7 @@ async fn run() {
let buffer_size = (padded_bytes_per_row * texture_size) as wgpu::BufferAddress;
let buffer_desc = wgpu::BufferDescriptor {
size: buffer_size,
usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::MAP_READ,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
label: Some("Output Buffer"),
mapped_at_creation: false,
};
@ -103,6 +103,7 @@ async fn run() {
encoder.copy_texture_to_buffer(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &render_target.texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
@ -190,7 +191,7 @@ fn create_render_pipeline(
targets: &[wgpu::ColorTargetState {
format: target.desc.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {

@ -8,9 +8,9 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
wgpu = "0.9"
wgpu = "0.10"
pollster = "0.2"
imgui = "0.7"
imgui-wgpu = "0.15"
imgui-wgpu = "0.17"
imgui-winit-support = "0.7"
framework = { path = "../framework" }

@ -14,7 +14,7 @@ struct ImguiDemo {
impl framework::Demo for ImguiDemo {
fn init(display: &framework::Display) -> Result<Self, Error> {
let canvas = framework::ShaderCanvasBuilder::new()
.display_format(display.sc_desc.format)
.display_format(display.config.format)
.build(&display.device)?;
let mut imgui = imgui::Context::create();
@ -39,7 +39,7 @@ impl framework::Demo for ImguiDemo {
}]);
let renderer_config = RendererConfig {
texture_format: display.sc_desc.format,
texture_format: display.config.format,
..Default::default()
};
let renderer = Renderer::new(&mut imgui, &display.device, &display.queue, renderer_config);
@ -102,8 +102,8 @@ impl framework::Demo for ImguiDemo {
&display.queue,
&mut encoder,
&output.view,
display.sc_desc.width as f32,
display.sc_desc.height as f32,
display.config.width as f32,
display.config.height as f32,
);
// Render the UI

@ -11,7 +11,7 @@ anyhow = "1.0"
bytemuck = { version = "1.4", features = [ "derive" ] }
cgmath = "0.18"
pollster = "0.2"
wgpu = "0.9"
wgpu = "0.10"
wgpu_glyph = "0.12"
rand = "0.8"
rodio = "0.14"

@ -17,7 +17,7 @@ impl Vertex {
pub const SIZE: wgpu::BufferAddress = std::mem::size_of::<Self>() as wgpu::BufferAddress;
pub const DESC: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
array_stride: Self::SIZE,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![
0 => Float32x2
],
@ -111,7 +111,7 @@ impl StagingBuffer {
StagingBuffer {
buffer: device.create_buffer_init(&BufferInitDescriptor {
contents: bytemuck::cast_slice(data),
usage: wgpu::BufferUsage::COPY_SRC,
usage: wgpu::BufferUsages::COPY_SRC,
label: Some("Staging Buffer"),
}),
size: size_of_slice(data) as wgpu::BufferAddress,

@ -19,8 +19,7 @@ pub struct Render {
adapter: wgpu::Adapter,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
index_buffer: wgpu::Buffer,
@ -30,18 +29,18 @@ pub struct Render {
impl Render {
pub fn width(&self) -> f32 {
self.sc_desc.width as f32
self.config.width as f32
}
#[allow(dead_code)]
pub fn height(&self) -> f32 {
self.sc_desc.height as f32
self.config.height as f32
}
pub async fn new(window: &Window, video_mode: &VideoMode) -> Self {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@ -63,14 +62,14 @@ impl Render {
.unwrap();
let size = video_mode.size();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[],
@ -80,7 +79,7 @@ impl Render {
let pipeline = create_render_pipeline(
&device,
&pipeline_layout,
sc_desc.format,
config.format,
&[Vertex::DESC],
wgpu::include_spirv!("../../res/shaders/textured.vert.spv"),
wgpu::include_spirv!("../../res/shaders/textured.frag.spv"),
@ -89,20 +88,20 @@ impl Render {
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: Vertex::SIZE * 4 * 3,
usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: U32_SIZE * 6 * 3,
usage: wgpu::BufferUsage::INDEX | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let font = ab_glyph::FontArc::try_from_slice(FONT_BYTES).unwrap();
let glyph_brush =
wgpu_glyph::GlyphBrushBuilder::using_font(font).build(&device, sc_desc.format);
wgpu_glyph::GlyphBrushBuilder::using_font(font).build(&device, config.format);
let staging_belt = wgpu::util::StagingBelt::new(1024);
Self {
@ -110,8 +109,7 @@ impl Render {
adapter,
device,
queue,
sc_desc,
swap_chain,
config,
pipeline,
vertex_buffer,
index_buffer,
@ -186,16 +184,16 @@ impl Render {
&mut self.staging_belt,
&mut encoder,
&frame.output.view,
self.sc_desc.width,
self.sc_desc.height,
self.config.width,
self.config.height,
)
.unwrap();
self.staging_belt.finish();
self.queue.submit(iter::once(encoder.finish()));
}
Err(wgpu::SwapChainError::Outdated) => {
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
Err(wgpu::SurfaceError::Outdated) => {
self.surface.configure(&self.device, &self.config);
}
Err(e) => {
eprintln!("Error: {}", e);
@ -257,7 +255,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {

@ -12,7 +12,7 @@ raw-window-handle = "0.3"
winit = "0.25"
shaderc = "0.7"
cgmath = "0.18"
wgpu = "0.9"
wgpu = "0.10"
pollster = "0.2"
[[bin]]

@ -1,7 +1,7 @@
use std::num::NonZeroU32;
async fn run() {
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
@ -25,7 +25,7 @@ async fn run() {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_SRC | wgpu::TextureUsage::RENDER_ATTACHMENT,
usage: wgpu::TextureUsages::COPY_SRC | wgpu::TextureUsages::RENDER_ATTACHMENT,
label: None,
};
let texture = device.create_texture(&texture_desc);
@ -37,9 +37,9 @@ async fn run() {
let output_buffer_size = (u32_size * texture_size * texture_size) as wgpu::BufferAddress;
let output_buffer_desc = wgpu::BufferDescriptor {
size: output_buffer_size,
usage: wgpu::BufferUsage::COPY_DST
usage: wgpu::BufferUsages::COPY_DST
// this tells wpgu that we want to read this buffer from the cpu
| wgpu::BufferUsage::MAP_READ,
| wgpu::BufferUsages::MAP_READ,
label: None,
mapped_at_creation: false,
};
@ -71,12 +71,10 @@ async fn run() {
let vs_module = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Vertex Shader"),
source: vs_data,
flags: wgpu::ShaderFlags::default(),
});
let fs_module = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Fragment Shader"),
source: fs_data,
flags: wgpu::ShaderFlags::default(),
});
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -102,7 +100,7 @@ async fn run() {
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -154,6 +152,7 @@ async fn run() {
encoder.copy_texture_to_buffer(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,

@ -10,7 +10,7 @@ module.exports = {
},
themeConfig: {
author: {
name: 'Benjamin R Hansen',
name: 'Benjamin Hansen',
twitter: 'https://twitter.com/sotrh760',
},
displayAllHeaders: false,
@ -22,7 +22,7 @@ module.exports = {
collapsable: false,
children: [
'/beginner/tutorial1-window/',
'/beginner/tutorial2-swapchain/',
'/beginner/tutorial2-surface/',
'/beginner/tutorial3-pipeline/',
'/beginner/tutorial4-buffer/',
'/beginner/tutorial5-textures/',

@ -13,10 +13,13 @@ winit = "0.25"
cgmath = "0.18"
env_logger = "0.9"
log = "0.4"
wgpu = "0.9"
wgpu = "0.10"
pollster = "0.2"
```
## Using Rust's new resolver
As of version 0.10, wgpu require's cargo's [newest feature resolver](https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2). As a result you must include `resolver = 2` in either the `[package]` section of `Cargo.toml` if you are working on a single crate, or the `[workspace]` section of the root `Cargo.toml` in a workspace.
## The code
There's not much going on here yet, so I'm just going to post the code in full. Just paste this into your `main.rs` or equivalent.

@ -1,4 +1,4 @@
# The Swapchain
# The Surface
## First, some house keeping: State
For convenience we're going to pack all the fields into a struct, and create some methods on that.
@ -11,8 +11,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
}
@ -34,7 +33,7 @@ impl State {
todo!()
}
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
todo!()
}
}
@ -53,7 +52,7 @@ impl State {
// The instance is a handle to our GPU
// BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
let adapter = instance.request_adapter(
&wgpu::RequestAdapterOptions {
@ -63,7 +62,12 @@ impl State {
).await.unwrap();
```
The `surface` is used to create the `swap_chain`. Our `window` needs to implement [raw-window-handle](https://crates.io/crates/raw-window-handle)'s `HasRawWindowHandle` trait to access the native window implementation for `wgpu` to properly create the graphics backend. Fortunately, winit's `Window` fits the bill. We also need it to request our `adapter`.
### Instance and Adapter
The `instance` is the first thing you create when using wgpu. It's may purpose
is to create `Adapter`s and `Surface`s.
The `adapter` is a handle to our actual graphics card. You can use this get information about the graphics card such as its name and what backend the adapter uses. We use this to create our `Device` and `Queue` later.
<div class="note">
@ -71,20 +75,28 @@ The options I've passed to `request_adapter` aren't guaranteed to work for all d
```rust
let adapter = instance
.enumerate_adapters(wgpu::BackendBit::PRIMARY)
.enumerate_adapters(wgpu::Backends::all())
.filter(|adapter| {
// Check if this adapter supports our surface
adapter.get_swap_chain_preferred_format(&surface).is_some()
surface.get_preferred_format(&adapter).is_some()
})
.first()
.unwrap()
```
For more fields you can use to refine you're search [check out the docs](https://docs.rs/wgpu/0.9.0/wgpu/struct.Adapter.html).
Another thing to note is that `Adapter`s are locked to a specific backend. If you are on Windows and have 2 graphics cards you'll have at least 4 adapters available to use, 2 Vulkan and 2 DirectX.
For more fields you can use to refine you're search [check out the docs](https://docs.rs/wgpu/0.10.1/wgpu/struct.Adapter.html).
</div>
We need the `adapter` to create the device and queue.
### The Surface
The `surface` is the part of the window that we draw to. We need it to draw directly to the screen. Our `window` needs to implement [raw-window-handle](https://crates.io/crates/raw-window-handle)'s `HasRawWindowHandle` trait to create a surface. Fortunately, winit's `Window` fits the bill. We also need it to request our `adapter`.
### Device and Queue
Let's use the `adapter` to create the device and queue.
```rust
let (device, queue) = adapter.request_device(
@ -101,43 +113,51 @@ The `features` field on `DeviceDescriptor`, allows us to specify what extra feat
<div class="note">
The device you have limits the features you can use. If you want to use certain features you may need to limit what devices you support, or provide work arounds.
The graphics card you have limits the features you can use. If you want to use certain features you may need to limit what devices you support, or provide work arounds.
You can get a list of features supported by your device using `adapter.features()`, or `device.features()`.
You can view a full list of features [here](https://docs.rs/wgpu/0.7.0/wgpu/struct.Features.html).
You can view a full list of features [here](https://docs.rs/wgpu/0.10.1/wgpu/struct.Features.html).
</div>
The `limits` field describes the limit of certain types of resource we can create. We'll use the defaults for this tutorial, so we can support most devices. You can view a list of limits [here](https://docs.rs/wgpu/0.7.0/wgpu/struct.Limits.html).
```rust
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
format: adapter.get_swap_chain_preferred_format(&surface).unwrap(),
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_preferred_format(&adapter).unwrap(),
width: size.width,
height: size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
```
Here we are defining and creating the `swap_chain`. The `usage` field describes how the `swap_chain`'s underlying textures will be used. `RENDER_ATTACHMENT` specifies that the textures will be used to write to the screen (we'll talk about more `TextureUsage`s later).
The `format` defines how the `swap_chain`s textures will be stored on the gpu. Different displays prefer different formats. We use `adapter.get_swap_chain_preferred_format()` to figure out the best format to use.
Here we are defining a config for our surface. This will define how the surface creates it's underlying `SurfaceTexture`s. We will talk about `SurfaceTexture` when we get to the `render` function. For now lets talk about some of the our configs fields.
`width` and `height`, are the width and height in pixels of the swap chain. This should usually be the width and height of the window.
The `usage` field describes how the `SurfaceTexture`s will be used. `RENDER_ATTACHMENT` specifies that the textures will be used to write to the screen (we'll talk about more `TextureUsages`s later).
The `present_mode` uses the `wgpu::PresentMode` enum which determines how to sync the swap chain with the display. You can see all the options [in the docs](https://docs.rs/wgpu/0.7.0/wgpu/enum.PresentMode.html)
The `format` defines how the `SurfaceTexture`s will be stored on the gpu. Different displays prefer different formats. We use `surface.get_preferred_format(&adapter)` to figure out the best format to use based on the display you're using.
At the end of the method, we simply return the resulting struct.
`width` and `height`, are the width and height in pixels of the `SurfaceTexture`. This should usually be the width and height of the window.
<div class="warning">
Make sure that the width and height of the `SurfaceTexture` are not 0, as that can cause your app to crash.
</div>
The `present_mode` uses the `wgpu::PresentMode` enum which determines how to sync the surface with the display. The option we picked `FIFO`, will cap the display rate at the displays framerate. This is essentially VSync. This is also the most optimal mode on mobile. There are other options and you can see all them [in the docs](https://docs.rs/wgpu/0.10.1/wgpu/enum.PresentMode.html)
Now that we've configured our surface properly we can add these new fields at the end of the method.
```rust
Self {
instance,
adapter,
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
}
}
@ -148,7 +168,7 @@ At the end of the method, we simply return the resulting struct.
We'll want to call this in our main method before we enter the event loop.
```rust
// Since main can't be async, we're going to need to block
// State::new uses async code, so we're going to wait for it to finish
let mut state = pollster::block_on(State::new(&window));
```
@ -159,21 +179,21 @@ You can use heavier libraries like [async_std](https://docs.rs/async_std) and [t
</div>
## resize()
If we want to support resizing in our application, we're going to need to recreate the `swap_chain` everytime the window's size changes. That's the reason we stored the physical `size` and the `sc_desc` used to create the swapchain. With all of these, the resize method is very simple.
If we want to support resizing in our application, we're going to need to reconfigure the `surface` everytime the window's size changes. That's the reason we stored the physical `size` and the `config` used to configure the `surface`. With all of these, the resize method is very simple.
```rust
// impl State
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
```
There's nothing really different here from creating the `swap_chain` initially, so I won't get into it.
There's nothing really different here from configurating the `surface` initially, so I won't get into it.
We call this method in `main()` in the event loop for the following events.
@ -254,20 +274,27 @@ fn update(&mut self) {
}
```
We'll add some code here later on to move around objects.
## render()
Here's where the magic happens. First we need to get a frame to render to. This will include a `wgpu::Texture` and `wgpu::TextureView` that will hold the actual image we're drawing to (we'll cover this more when we talk about textures).
Here's where the magic happens. First we need to get a frame to render to.
```rust
// impl State
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
let frame = self
.swap_chain
.get_current_frame()?
.output;
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
let output = self.surface.get_current_frame()?.output;
```
The `get_current_frame` function will wait for the `surface` to provide a new `SurfaceTexture` that we will render to. We'll store this in `output` for later.
```rust
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
```
This line creates a `TextureView` with default settings. We need to do this because we want to control how the render code interacts with the texture.
We also need to create a `CommandEncoder` to create the actual commands to send to the gpu. Most modern graphics frameworks expect commands to be stored in a command buffer before being sent to the gpu. The `encoder` builds a command buffer that we can then send to the gpu.
```rust
@ -282,21 +309,19 @@ Now we can actually get to clearing the screen (long time coming). We need to us
{
let _render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[
wgpu::RenderPassColorAttachment {
view: &frame.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
}
}
],
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
});
}
@ -325,10 +350,10 @@ event_loop.run(move |event, _, control_flow| {
state.update();
match state.render() {
Ok(_) => {}
// Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
// Reconfigure the surface if lost
Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame
Err(e) => eprintln!("{:?}", e),
}
@ -361,11 +386,13 @@ Some of you may be able to tell what's going on just by looking at it, but I'd b
}
```
A `RenderPassDescriptor` only has three fields: `label`, `color_attachments` and `depth_stencil_attachment`. The `color_attachements` describe where we are going to draw our color to. We'll use `depth_stencil_attachment` later, but we'll set it to `None` for now.
A `RenderPassDescriptor` only has three fields: `label`, `color_attachments` and `depth_stencil_attachment`. The `color_attachements` describe where we are going to draw our color to. We use the `TextureView` we created earlier to make sure that we render to the screen.
We'll use `depth_stencil_attachment` later, but we'll set it to `None` for now.
```rust
wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
@ -375,15 +402,15 @@ wgpu::RenderPassColorAttachment {
a: 1.0,
}),
store: true,
}
},
}
```
The `RenderPassColorAttachment` has the `view` field which informs `wgpu` what texture to save the colors to. In this case we specify `frame.view` that we created using `swap_chain.get_current_frame()`. This means that any colors we draw to this attachment will get drawn to the screen.
The `RenderPassColorAttachment` has the `view` field which informs `wgpu` what texture to save the colors to. In this case we specify `frame.view` that we created using `surface.get_current_frame()`. This means that any colors we draw to this attachment will get drawn to the screen.
The `resolve_target` is the texture that will receive the resolved output. This will be the same as `attachment` unless multisampling is enabled. We don't need to specify this, so we leave it as `None`.
The `ops` field takes a `wpgu::Operations` object. This tells wgpu what to do with the colors on the screen (specified by `frame.view`). The `load` field tells wgpu how to handle colors stored from the previous frame. Currently we are clearing the screen with a bluish color.
The `ops` field takes a `wpgu::Operations` object. This tells wgpu what to do with the colors on the screen (specified by `frame.view`). The `load` field tells wgpu how to handle colors stored from the previous frame. Currently we are clearing the screen with a bluish color. The `store` field tells wgpu with we want to store the rendered results to the `Texture` behind our `TextureView` (in this case it's the `SurfaceTexture`). We use `true` as we do want to store our render results. There are cases when you wouldn't want to but those
<div class="note">
@ -393,6 +420,10 @@ It's not uncommon to not clear the screen if the screen is going to be completel
</div>
## Validation Errors?
If wgpu is using Vulkan on your machine, you may run into validation errors if you are running an older version of the Vulkan SDK. You should be using at least version `1.2.182` as older versions can give out some false positives. If errors persist, you may have encountered a bug in wgpu. You can post an issue at [https://github.com/gfx-rs/wgpu](https://github.com/gfx-rs/wgpu)
## Challenge
Modify the `input()` method to capture mouse events, and update the clear color using that. *Hint: you'll probably need to use `WindowEvent::CursorMoved`*.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

@ -130,8 +130,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
// NEW!
render_pipeline: wgpu::RenderPipeline,
@ -174,9 +173,9 @@ let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescrip
module: &shader,
entry_point: "main",
targets: &[wgpu::ColorTargetState { // 4.
format: sc_desc.format,
format: config.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
// continued ...
@ -185,8 +184,8 @@ let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescrip
Two things to note here:
1. Here you can specify which function inside of the shader should be called, which is known as the `entry_point`. These are the functions we marked with `[[stage(vertex)]]` and `[[stage(fragment)]]`
2. The `buffers` field tells `wgpu` what type of vertices we want to pass to the vertex shader. We're specifying the vertices in the vertex shader itself so we'll leave this empty. We'll put something there in the next tutorial.
3. The `fragment` is technically optional, so you have to wrap it in `Some()`. We need it if we want to store color data to the `swap_chain`.
4. The `targets` field tells `wgpu` what color outputs it should set up.Currently we only need one for the `swap_chain`. We use the `swap_chain`'s format so that copying to it is easy, and we specify that the blending should just replace old pixel data with new data. We also tell `wgpu` to write to all colors: red, blue, green, and alpha. *We'll talk more about*`color_state` *when we talk about textures.*
3. The `fragment` is technically optional, so you have to wrap it in `Some()`. We need it if we want to store color data to the `surface`.
4. The `targets` field tells `wgpu` what color outputs it should set up.Currently we only need one for the `surface`. We use the `surface`'s format so that copying to it is easy, and we specify that the blending should just replace old pixel data with new data. We also tell `wgpu` to write to all colors: red, blue, green, and alpha. *We'll talk more about*`color_state` *when we talk about textures.*
```rust
primitive: wgpu::PrimitiveState {
@ -235,8 +234,7 @@ Self {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
// NEW!
render_pipeline,
@ -257,7 +255,7 @@ If you run your program now, it'll take a little longer to start, but it will st
color_attachments: &[
// This is what [[location(0)]] in the fragment shader targets
wgpu::RenderPassColorAttachment {
view: &frame.view,
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(

@ -57,7 +57,7 @@ let vertex_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
}
);
```
@ -105,8 +105,7 @@ Self {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -121,7 +120,7 @@ A `VertexBufferLayout` defines how a buffer is layed out in memory. Without this
```rust
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress, // 1.
step_mode: wgpu::InputStepMode::Vertex, // 2.
step_mode: wgpu::VertexStepMode::Vertex, // 2.
attributes: &[ // 3.
wgpu::VertexAttribute {
offset: 0, // 4.
@ -138,7 +137,7 @@ wgpu::VertexBufferLayout {
```
1. The `array_stride` defines how wide a vertex is. When the shader goes to read the next vertex, it will skip over `array_stride` number of bytes. In our case, array_stride will probably be 24 bytes.
2. `step_mode` tells the pipeline how often it should move to the next vertex. This seems redundant in our case, but we can specify `wgpu::InputStepMode::Instance` if we only want to change vertices when we start drawing a new instance. We'll cover instancing in a later tutorial.
2. `step_mode` tells the pipeline how often it should move to the next vertex. This seems redundant in our case, but we can specify `wgpu::VertexStepMode::Instance` if we only want to change vertices when we start drawing a new instance. We'll cover instancing in a later tutorial.
3. Vertex attributes describe the individual parts of the vertex. Generally this is a 1:1 mapping with a struct's fields, which it is in our case.
4. This defines the `offset` in bytes that this attribute starts. The first attribute is usually zero, and any future attributes are the collective `size_of` the previous attributes data.
5. This tells the shader what location to store this attribute at. For example `[[location(0)]] x: vec3<f32>` in the vertex shader would correspond to the position field of the struct, while `[[location(1)]] x: vec3<f32>` would be the color field.
@ -156,7 +155,7 @@ impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -181,7 +180,7 @@ Specifying the attributes as we did now is quite verbose. We could use the `vert
```rust
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
}
```
@ -241,8 +240,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
render_pipeline,
vertex_buffer,
num_vertices,
@ -350,7 +348,7 @@ let vertex_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(VERTICES),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
}
);
// NEW!
@ -358,7 +356,7 @@ let index_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
}
);
let num_indices = INDICES.len() as u32;
@ -371,8 +369,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -389,8 +386,7 @@ Self {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -422,7 +418,7 @@ With all that you should have a garishly magenta pentagon in your window.
If you use a color picker on the magenta pentagon, you'll get a hex value of #BC00BC. If you convert this to RGB values you'll get (188, 0, 188). Dividing these values by 255 to get them into the [0, 1] range we get roughly (0.737254902, 0, 0.737254902). This is not the same as we are using for our vertex colors which is (0.5, 0.0, 0.5). The reason for this has to do with color spaces.
Most monitors use a color space know as sRGB. Our swap chain is (most likely depending on what is returned from `adapter.get_swap_chain_preferred_format()`) using an sRGB texture format. The sRGB format stores colors according to their relative brightness instead of their actual brightness. The reason for this is that our eyes don't perceive light linearly. We notice more differences in darker colors than we do lighter colors.
Most monitors use a color space know as sRGB. Our surface is (most likely depending on what is returned from `surface.get_preferred_format()`) using an sRGB texture format. The sRGB format stores colors according to their relative brightness instead of their actual brightness. The reason for this is that our eyes don't perceive light linearly. We notice more differences in darker colors than we do lighter colors.
You get an approximation of the correct color using the following formula: `srgb_color = (rgb_color / 255) ^ 2.2`. Doing this with an RGB value of (188, 0, 188) will give us (0.511397819, 0.0, 0.511397819). A little off from our (0.5, 0.0, 0.5). While you could tweak the formula to get the desired values, you'll likely save a lot of time by using textures instead as they are stored as sRGB by default, so they don't suffer from the same color inaccuracies that vertex colors do. We'll cover textures in the next lesson.

@ -12,10 +12,10 @@ If we want to map an image to our mesh, we first need an image. Let's use this h
We'll use the [image crate](https://crates.io/crates/image) to load our tree. We already added to our dependencies in the first section, so all we have to do is use it.
In `State`'s `new()` method add the following just after creating the `swap_chain`:
In `State`'s `new()` method add the following just after configuring the `surface`:
```rust
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
// NEW!
let diffuse_bytes = include_bytes!("happy-tree.png");
@ -48,7 +48,7 @@ let diffuse_texture = device.create_texture(
format: wgpu::TextureFormat::Rgba8UnormSrgb,
// SAMPLED tells wgpu that we want to use this texture in shaders
// COPY_DST means that we want to copy data to this texture
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: Some("diffuse_texture"),
}
);
@ -87,7 +87,7 @@ let buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Temp Buffer"),
contents: &diffuse_rgba,
usage: wgpu::BufferUsage::COPY_SRC,
usage: wgpu::BufferUsages::COPY_SRC,
}
);
@ -169,7 +169,7 @@ let texture_bind_group_layout = device.create_bind_group_layout(
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
@ -179,7 +179,7 @@ let texture_bind_group_layout = device.create_bind_group_layout(
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
// This is only for TextureSampleType::Depth
comparison: false,
@ -228,8 +228,7 @@ struct State {
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
config: wgpu::SurfaceConfiguration,
size: winit::dpi::PhysicalSize<u32>,
render_pipeline: wgpu::RenderPipeline,
vertex_buffer: wgpu::Buffer,
@ -249,8 +248,7 @@ impl State {
surface,
device,
queue,
sc_desc,
swap_chain,
config,
size,
render_pipeline,
vertex_buffer,
@ -318,7 +316,7 @@ impl Vertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -434,7 +432,7 @@ winit = "0.25"
env_logger = "0.9"
log = "0.4"
pollster = "0.2"
wgpu = "0.9"
wgpu = "0.10"
bytemuck = { version = "1.4", features = [ "derive" ] }
anyhow = "1.0" // NEW!
```
@ -484,12 +482,13 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
}
);
queue.write_texture(
wgpu::ImageCopyTexture {
aspect: wgpu::TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
@ -532,7 +531,7 @@ mod texture;
The texture creation code in `new()` now gets a lot simpler:
```rust
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
let diffuse_bytes = include_bytes!("happy-tree.png"); // CHANGED!
let diffuse_texture = texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap(); // CHANGED!

@ -69,7 +69,7 @@ async fn new(window: &Window) -> Self {
target: (0.0, 0.0, 0.0).into(),
// which way is "up"
up: cgmath::Vector3::unit_y(),
aspect: sc_desc.width as f32 / sc_desc.height as f32,
aspect: config.width as f32 / config.height as f32,
fovy: 45.0,
znear: 0.1,
zfar: 100.0,
@ -126,7 +126,7 @@ let camera_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Camera Buffer"),
contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}
);
```
@ -140,7 +140,7 @@ let camera_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupL
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -408,7 +408,7 @@ fn input(&mut self, event: &WindowEvent) -> bool {
Up to this point, the camera controller isn't actually doing anything. The values in our uniform buffer need to be updated. There are a few main methods to do that.
1. We can create a separate buffer and copy it's contents to our `camera_buffer`. The new buffer is known as a staging buffer. This method is usually how it's done as it allows the contents of the main buffer (in this case `camera_buffer`) to only be accessible by the gpu. The gpu can do some speed optimizations which it couldn't if we could access the buffer via the cpu.
2. We can call on of the mapping method's `map_read_async`, and `map_write_async` on the buffer itself. These allow us to access a buffer's contents directly, but requires us to deal with the `async` aspect of these methods this also requires our buffer to use the `BufferUsage::MAP_READ` and/or `BufferUsage::MAP_WRITE`. We won't talk about it here, but you check out [Wgpu without a window](../../showcase/windowless) tutorial if you want to know more.
2. We can call on of the mapping method's `map_read_async`, and `map_write_async` on the buffer itself. These allow us to access a buffer's contents directly, but requires us to deal with the `async` aspect of these methods this also requires our buffer to use the `BufferUsages::MAP_READ` and/or `BufferUsages::MAP_WRITE`. We won't talk about it here, but you check out [Wgpu without a window](../../showcase/windowless) tutorial if you want to know more.
3. We can use `write_buffer` on `queue`.
We're going to use option number 3.

@ -123,7 +123,7 @@ let instance_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
}
);
```
@ -139,7 +139,7 @@ impl InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,

@ -26,10 +26,10 @@ Let's make a function to create the depth texture in `texture.rs`.
impl Texture {
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; // 1.
pub fn create_depth_texture(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, label: &str) -> Self {
pub fn create_depth_texture(device: &wgpu::Device, config: &wgpu::SurfaceConfiguration, label: &str) -> Self {
let size = wgpu::Extent3d { // 2.
width: sc_desc.width,
height: sc_desc.height,
width: config.width,
height: config.height,
depth_or_array_layers: 1,
};
let desc = wgpu::TextureDescriptor {
@ -39,8 +39,8 @@ impl Texture {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT // 3.
| wgpu::TextureUsage::SAMPLED,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT // 3.
| wgpu::TextureUsages::TEXTURE_BINDING,
};
let texture = device.create_texture(&desc);
@ -66,7 +66,7 @@ impl Texture {
```
1. We need the DEPTH_FORMAT for when we create the depth stage of the `render_pipeline` and creating the depth texture itself.
2. Our depth texture needs to be the same size as our screen if we want things to render correctly. We can use our `sc_desc` to make sure that our depth texture is the same size as our swap chain images.
2. Our depth texture needs to be the same size as our screen if we want things to render correctly. We can use our `config` to make sure that our depth texture is the same size as our surface textures.
3. Since we are rendering to this texture, we need to add the `RENDER_ATTACHMENT` flag to it.
4. We technically don't *need* a sampler for a depth texture, but our `Texture` struct requires it, and we need one if we ever want to sample it.
5. If we do decide to render our depth texture, we need to use `CompareFunction::LessEqual`. This is due to how the `samplerShadow` and `sampler2DShadow()` interacts with the `texture()` function in GLSL.
@ -74,7 +74,7 @@ impl Texture {
We create our `depth_texture` in `State::new()`.
```rust
let depth_texture = texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
let depth_texture = texture::Texture::create_depth_texture(&device, &config, "depth_texture");
```
We need to modify our `render_pipeline` to allow depth testing.
@ -129,13 +129,13 @@ We need to remember to change the `resize()` method to create a new `depth_textu
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
// ...
self.depth_texture = texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
self.depth_texture = texture::Texture::create_depth_texture(&self.device, &self.config, "depth_texture");
// ...
}
```
Make sure you update the `depth_texture` *after* you update `sc_desc`. If you don't, your program will crash as the `depth_texture` will be a different size than the `swap_chain` texture.
Make sure you update the `depth_texture` *after* you update `config`. If you don't, your program will crash as the `depth_texture` will be a different size than the `surface` texture.
The last change we need to make is in the `render()` function. We've created the `depth_texture`, but we're not currently using it. We use it by attaching it to the `depth_stencil_attachment` of a render pass.

@ -37,7 +37,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -126,7 +126,15 @@ glob = "0.3"
## Loading models with TOBJ
We're going to use the [tobj](https://docs.rs/tobj/0.1.12/tobj/) library to load our model. Before we can load our model though, we need somewhere to put it.
We're going to use the [tobj](https://docs.rs/tobj/3.0/tobj/) library to load our model. Let's add it to our `Cargo.toml`.
```toml
[dependencies]
# other dependencies...
tobj = "3.0"
```
Before we can load our model though, we need somewhere to put it.
```rust
// model.rs
@ -263,14 +271,14 @@ impl Model {
&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Vertex Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&vertices),
usage: wgpu::BufferUsage::VERTEX,
usage: wgpu::BufferUsages::VERTEX,
}
);
let index_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", path.as_ref())),
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
}
);

@ -46,7 +46,7 @@ let light_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Light VB"),
contents: bytemuck::cast_slice(&[light_uniform]),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}
);
```
@ -58,7 +58,7 @@ let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@ -137,7 +137,7 @@ fn create_render_pipeline(
alpha: wgpu::BlendComponent::REPLACE,
color: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrite::ALL,
write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
@ -180,7 +180,7 @@ let render_pipeline = {
create_render_pipeline(
&device,
&render_pipeline_layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc(), InstanceRaw::desc()],
shader,
@ -294,7 +294,7 @@ let light_render_pipeline = {
create_render_pipeline(
&device,
&layout,
sc_desc.format,
config.format,
Some(texture::Texture::DEPTH_FORMAT),
&[model::ModelVertex::desc()],
shader,
@ -439,7 +439,7 @@ Finally we want to add Light rendering to our render passes.
```rust
impl State {
// ...
fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
// ...
render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
@ -628,7 +628,7 @@ impl model::Vertex for InstanceRaw {
// We need to switch from using a step mode of Vertex to Instance
// This means that our shaders will only change to use the next
// instance when the shader starts processing a new instance
step_mode: wgpu::InputStepMode::Instance,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
wgpu::VertexAttribute {
offset: 0,
@ -820,7 +820,7 @@ let camera_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupL
entries: &[
wgpu::BindGroupLayoutBinding {
// ...
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, // Updated!
visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, // Updated!
// ...
},
// ...

@ -30,7 +30,7 @@ let texture_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroup
// normal map
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -40,7 +40,7 @@ let texture_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroup
},
wgpu::BindGroupLayoutEntry {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@ -190,7 +190,7 @@ impl Vertex for ModelVertex {
use std::mem;
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<ModelVertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
// ...
@ -425,7 +425,7 @@ pub fn from_image(
} else {
wgpu::TextureFormat::Rgba8UnormSrgb
},
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
});
// ...

@ -284,7 +284,7 @@ impl State {
// UPDATED!
let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
let projection = camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
let projection = camera::Projection::new(config.width, config.height, cgmath::Deg(45.0), 0.1, 100.0);
let camera_controller = camera::CameraController::new(4.0, 0.4);
// ...

@ -92,7 +92,7 @@ impl Model {
&wgpu::util::BufferInitDescriptor {
label: Some(&format!("{:?} Index Buffer", m.name)), // UPDATED!
contents: bytemuck::cast_slice(&m.mesh.indices),
usage: wgpu::BufferUsage::INDEX,
usage: wgpu::BufferUsages::INDEX,
}
);
// ...

@ -27,7 +27,7 @@ The `wgpu_glyph`, and `imgui-wgpu` crates currently depend on `wgpu` 0.7, which
* `CullMode` is no longer a thing, instead `PrimitiveState::cull_mode` will require an `Option<Face>`
* Added `clamp_depth` and `conservative` to `PrimitiveState`. Part of this means that `DepthStencilState` no longer has a `clamp_depth` field.
* `color_blend` and `alpha_blend` have been moved into the new `blend` field with accepts an `Option<wgpu::BlendState>`
* `adapter.get_swap_chain_preferred_format()` now returns an `Option<wgpu::TextureFormat>`
* `adapter.get_preferred_format()` now returns an `Option<wgpu::TextureFormat>`
* `wgpu::RenderPassColorAttachmentDescriptor` has been renamed `wgpu::RenderPassColorAttachement` and the `attachment` field has been renamed to `view`
* `wgpu::RenderPassDepthStencialAttachmentDescriptor` also loses the `Descriptor` part of it's name. `attachment` gets renamed to `view` as well.
* `wgpu::TextureCopyView` has been renamed to `wgpu::ImageCopyTexture`. This is a typedef for `wgpu::ImageCopyTextureBase<T>`
@ -42,7 +42,7 @@ There were a lot of changes particularly to the `RenderPipelineDescriptor`. Most
School is starting to ramp up, so I haven't had as much time to work on the site as I would like to. Because of that there were some issues piling up. I decided to tackle a bunch of them in one go. Here's a snapshot of what I did:
* The tutorial now handles `SwapChainError` properly
* The tutorial now handles `SurfaceError` properly
* I'm now using bytemuck's derive feature on all buffer data structs.
* The [instancing tutorial](../beginner/tutorial7-instancing) now uses vertex buffers instead of storage buffers.
* `build.rs` now updates when individual shaders are changed, not whenever `/src` is changed.
@ -88,7 +88,7 @@ Up to this point, we created textures manually everytime. I've pulled out the te
## Fixed panics do to not specifying the correct `usage`
Wgpu has become more strict about what `BufferUsage`s and `TextureUsage`s are required when performing certain operations. For example int the [Wgpu without a window example](/intermediate/windowless/), the `texture_desc` only specified the usage to by `COPY_SRC`. This caused a crash when the `texture` was used as a render target. Adding `OUTPUT_ATTACHMENT` fixed the issue.
Wgpu has become more strict about what `BufferUsages`s and `TextureUsages`s are required when performing certain operations. For example int the [Wgpu without a window example](/intermediate/windowless/), the `texture_desc` only specified the usage to by `COPY_SRC`. This caused a crash when the `texture` was used as a render target. Adding `OUTPUT_ATTACHMENT` fixed the issue.
## Updating Winit from 0.20.0-alpha5 to 0.20

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save