mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 08:13:27 +00:00
[rs] Merge #127
127: Use u8 for buffer mapping r=kvark a=Coder-256 cc @kvark @grovesNL This is a temporary solution for #119, and a follow-up for #126. Co-authored-by: Jacob Greenfield <jacob@jacobgreenfield.me>
This commit is contained in:
commit
1968eb81e7
@ -37,7 +37,6 @@ rev = "73b33ea76e2f91b3114aa7640b1d60518d39f915"
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
raw-window-handle = "0.3"
|
||||
zerocopy = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
cgmath = "0.17"
|
||||
@ -46,3 +45,4 @@ glsl-to-spirv = "0.1"
|
||||
log = "0.4"
|
||||
png = "0.15"
|
||||
winit = "0.20.0-alpha4"
|
||||
zerocopy = "0.2"
|
||||
|
@ -12,7 +12,8 @@ fn main() {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
|
@ -1,8 +1,10 @@
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct Vertex {
|
||||
_pos: [f32; 4],
|
||||
_tex_coord: [f32; 2],
|
||||
@ -107,7 +109,10 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
use std::mem;
|
||||
|
||||
let mut init_encoder =
|
||||
@ -116,13 +121,12 @@ impl framework::Example for Example {
|
||||
// Create the vertex and index buffers
|
||||
let vertex_size = mem::size_of::<Vertex>();
|
||||
let (vertex_data, index_data) = create_vertices();
|
||||
let vertex_buf = device
|
||||
.create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX)
|
||||
.fill_from_slice(&vertex_data);
|
||||
|
||||
let index_buf = device
|
||||
.create_buffer_mapped(index_data.len(), wgpu::BufferUsage::INDEX)
|
||||
.fill_from_slice(&index_data);
|
||||
let vertex_buf =
|
||||
device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX);
|
||||
|
||||
let index_buf =
|
||||
device.create_buffer_with_data(index_data.as_bytes(), wgpu::BufferUsage::INDEX);
|
||||
|
||||
// Create pipeline layout
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
@ -130,9 +134,7 @@ impl framework::Example for Example {
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
},
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1,
|
||||
@ -171,9 +173,8 @@ impl framework::Example for Example {
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
|
||||
});
|
||||
let texture_view = texture.create_default_view();
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(&texels);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(texels.as_slice(), wgpu::BufferUsage::COPY_SRC);
|
||||
init_encoder.copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
buffer: &temp_buf,
|
||||
@ -208,12 +209,10 @@ impl framework::Example for Example {
|
||||
});
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let uniform_buf = device
|
||||
.create_buffer_mapped(
|
||||
16,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
.fill_from_slice(mx_ref);
|
||||
let uniform_buf = device.create_buffer_with_data(
|
||||
mx_ref.as_bytes(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// Create bind group
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@ -310,13 +309,16 @@ impl framework::Example for Example {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> Option<wgpu::CommandBuffer> {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(mx_ref);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
@ -324,7 +326,11 @@ impl framework::Example for Example {
|
||||
Some(encoder.finish())
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
fn render(
|
||||
&mut self,
|
||||
frame: &wgpu::SwapChainOutput,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
{
|
||||
|
@ -7,7 +7,8 @@ fn main() {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("{:?}", adapter.get_info())
|
||||
}
|
||||
|
@ -99,7 +99,8 @@ pub fn run<E: Example>(title: &str) {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
@ -163,7 +164,8 @@ pub fn run<E: Example>(title: &str) {
|
||||
}
|
||||
},
|
||||
event::Event::EventsCleared => {
|
||||
let frame = swap_chain.get_next_texture()
|
||||
let frame = swap_chain
|
||||
.get_next_texture()
|
||||
.expect("Timeout when acquiring next swap chain texture");
|
||||
let command_buf = example.render(&frame, &device);
|
||||
queue.submit(&[command_buf]);
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::str::FromStr;
|
||||
use std::{convert::TryInto as _, str::FromStr};
|
||||
use zerocopy::AsBytes as _;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
@ -12,14 +13,16 @@ fn main() {
|
||||
.map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
|
||||
.collect();
|
||||
|
||||
let size = (numbers.len() * std::mem::size_of::<u32>()) as wgpu::BufferAddress;
|
||||
let slice_size = numbers.len() * std::mem::size_of::<u32>();
|
||||
let size = slice_size as wgpu::BufferAddress;
|
||||
|
||||
let adapter = wgpu::Adapter::request(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
@ -29,16 +32,13 @@ fn main() {
|
||||
});
|
||||
|
||||
let cs = include_bytes!("shader.comp.spv");
|
||||
let cs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap());
|
||||
let cs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap());
|
||||
|
||||
let staging_buffer = device
|
||||
.create_buffer_mapped(
|
||||
numbers.len(),
|
||||
wgpu::BufferUsage::MAP_READ
|
||||
| wgpu::BufferUsage::COPY_DST
|
||||
| wgpu::BufferUsage::COPY_SRC,
|
||||
)
|
||||
.fill_from_slice(&numbers);
|
||||
let staging_buffer = device.create_buffer_with_data(
|
||||
numbers.as_slice().as_bytes(),
|
||||
wgpu::BufferUsage::MAP_READ | wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::COPY_SRC,
|
||||
);
|
||||
|
||||
let storage_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size,
|
||||
@ -48,13 +48,14 @@ fn main() {
|
||||
});
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer { dynamic: false, readonly: false },
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
readonly: false,
|
||||
},
|
||||
],
|
||||
}],
|
||||
});
|
||||
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@ -92,9 +93,15 @@ fn main() {
|
||||
|
||||
queue.submit(&[encoder.finish()]);
|
||||
|
||||
staging_buffer.map_read_async(0, numbers.len(), |result: wgpu::BufferMapAsyncResult<&[u32]>| {
|
||||
// FIXME: Align and use `LayoutVerified`
|
||||
staging_buffer.map_read_async(0, slice_size, |result| {
|
||||
if let Ok(mapping) = result {
|
||||
println!("Times: {:?}", mapping.data);
|
||||
let times: Box<[u32]> = mapping
|
||||
.data
|
||||
.chunks_exact(4)
|
||||
.map(|b| u32::from_ne_bytes(b.try_into().unwrap()))
|
||||
.collect();
|
||||
println!("Times: {:?}", times);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
fn main() {
|
||||
use winit::{
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
event,
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
};
|
||||
|
||||
env_logger::init();
|
||||
@ -10,9 +10,7 @@ fn main() {
|
||||
#[cfg(not(feature = "gl"))]
|
||||
let (_window, size, surface) = {
|
||||
let window = winit::window::Window::new(&event_loop).unwrap();
|
||||
let size = window
|
||||
.inner_size()
|
||||
.to_physical(window.hidpi_factor());
|
||||
let size = window.inner_size().to_physical(window.hidpi_factor());
|
||||
|
||||
let surface = wgpu::Surface::create(&window);
|
||||
(window, size, surface)
|
||||
@ -43,7 +41,8 @@ fn main() {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
@ -53,14 +52,15 @@ fn main() {
|
||||
});
|
||||
|
||||
let vs = include_bytes!("shader.vert.spv");
|
||||
let vs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap());
|
||||
let vs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap());
|
||||
|
||||
let fs = include_bytes!("shader.frag.spv");
|
||||
let fs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap());
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap());
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[],
|
||||
});
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[] });
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &bind_group_layout,
|
||||
bindings: &[],
|
||||
@ -135,7 +135,8 @@ fn main() {
|
||||
_ => {}
|
||||
},
|
||||
event::Event::EventsCleared => {
|
||||
let frame = swap_chain.get_next_texture()
|
||||
let frame = swap_chain
|
||||
.get_next_texture()
|
||||
.expect("Timeout when acquiring next swap chain texture");
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
@ -1,10 +1,12 @@
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
const TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8UnormSrgb;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct Vertex {
|
||||
#[allow(dead_code)]
|
||||
pos: [f32; 4],
|
||||
@ -96,14 +98,10 @@ impl Example {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
});
|
||||
|
||||
let vs_bytes = framework::load_glsl(
|
||||
include_str!("blit.vert"),
|
||||
framework::ShaderStage::Vertex,
|
||||
);
|
||||
let fs_bytes = framework::load_glsl(
|
||||
include_str!("blit.frag"),
|
||||
framework::ShaderStage::Fragment,
|
||||
);
|
||||
let vs_bytes =
|
||||
framework::load_glsl(include_str!("blit.vert"), framework::ShaderStage::Vertex);
|
||||
let fs_bytes =
|
||||
framework::load_glsl(include_str!("blit.frag"), framework::ShaderStage::Fragment);
|
||||
let vs_module = device.create_shader_module(&vs_bytes);
|
||||
let fs_module = device.create_shader_module(&fs_bytes);
|
||||
|
||||
@ -152,15 +150,17 @@ impl Example {
|
||||
});
|
||||
|
||||
let views = (0 .. mip_count)
|
||||
.map(|mip| texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: TEXTURE_FORMAT,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
base_mip_level: mip,
|
||||
level_count: 1,
|
||||
base_array_layer: 0,
|
||||
array_layer_count: 1,
|
||||
}))
|
||||
.map(|mip| {
|
||||
texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
format: TEXTURE_FORMAT,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
base_mip_level: mip,
|
||||
level_count: 1,
|
||||
base_array_layer: 0,
|
||||
array_layer_count: 1,
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for target_mip in 1 .. mip_count as usize {
|
||||
@ -196,7 +196,10 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
use std::mem;
|
||||
|
||||
let mut init_encoder =
|
||||
@ -205,9 +208,8 @@ impl framework::Example for Example {
|
||||
// Create the vertex and index buffers
|
||||
let vertex_size = mem::size_of::<Vertex>();
|
||||
let vertex_data = create_vertices();
|
||||
let vertex_buf = device
|
||||
.create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX)
|
||||
.fill_from_slice(&vertex_data);
|
||||
let vertex_buf =
|
||||
device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX);
|
||||
|
||||
// Create pipeline layout
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
@ -215,9 +217,7 @@ impl framework::Example for Example {
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
},
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1,
|
||||
@ -254,12 +254,13 @@ impl framework::Example for Example {
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: TEXTURE_FORMAT,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::COPY_DST,
|
||||
usage: wgpu::TextureUsage::SAMPLED
|
||||
| wgpu::TextureUsage::OUTPUT_ATTACHMENT
|
||||
| wgpu::TextureUsage::COPY_DST,
|
||||
});
|
||||
let texture_view = texture.create_default_view();
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(&texels);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(texels.as_slice(), wgpu::BufferUsage::COPY_SRC);
|
||||
init_encoder.copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
buffer: &temp_buf,
|
||||
@ -294,12 +295,10 @@ impl framework::Example for Example {
|
||||
});
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let uniform_buf = device
|
||||
.create_buffer_mapped(
|
||||
16,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
.fill_from_slice(mx_ref);
|
||||
let uniform_buf = device.create_buffer_with_data(
|
||||
mx_ref.as_bytes(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// Create bind group
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@ -324,14 +323,10 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_bytes = framework::load_glsl(
|
||||
include_str!("draw.vert"),
|
||||
framework::ShaderStage::Vertex,
|
||||
);
|
||||
let fs_bytes = framework::load_glsl(
|
||||
include_str!("draw.frag"),
|
||||
framework::ShaderStage::Fragment,
|
||||
);
|
||||
let vs_bytes =
|
||||
framework::load_glsl(include_str!("draw.vert"), framework::ShaderStage::Vertex);
|
||||
let fs_bytes =
|
||||
framework::load_glsl(include_str!("draw.frag"), framework::ShaderStage::Fragment);
|
||||
let vs_module = device.create_shader_module(&vs_bytes);
|
||||
let fs_module = device.create_shader_module(&fs_bytes);
|
||||
|
||||
@ -364,13 +359,11 @@ impl framework::Example for Example {
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float4,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
},
|
||||
],
|
||||
attributes: &[wgpu::VertexAttributeDescriptor {
|
||||
format: wgpu::VertexFormat::Float4,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
}],
|
||||
}],
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
@ -393,13 +386,16 @@ impl framework::Example for Example {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> Option<wgpu::CommandBuffer> {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(mx_ref);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
@ -407,7 +403,11 @@ impl framework::Example for Example {
|
||||
Some(encoder.finish())
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
fn render(
|
||||
&mut self,
|
||||
frame: &wgpu::SwapChainOutput,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
{
|
||||
|
@ -10,10 +10,12 @@
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct Vertex {
|
||||
_pos: [f32; 2],
|
||||
_pos: [f32; 2],
|
||||
_color: [f32; 4],
|
||||
}
|
||||
|
||||
@ -31,7 +33,14 @@ struct Example {
|
||||
}
|
||||
|
||||
impl Example {
|
||||
fn create_pipeline(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, pipeline_layout: &wgpu::PipelineLayout, sample_count: u32) -> wgpu::RenderPipeline {
|
||||
fn create_pipeline(
|
||||
device: &wgpu::Device,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
pipeline_layout: &wgpu::PipelineLayout,
|
||||
sample_count: u32,
|
||||
) -> wgpu::RenderPipeline {
|
||||
println!("sample_count: {}", sample_count);
|
||||
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
@ -81,7 +90,11 @@ impl Example {
|
||||
})
|
||||
}
|
||||
|
||||
fn create_multisampled_framebuffer(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, sample_count: u32) -> wgpu::TextureView {
|
||||
fn create_multisampled_framebuffer(
|
||||
device: &wgpu::Device,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
sample_count: u32,
|
||||
) -> wgpu::TextureView {
|
||||
let multisampled_texture_extent = wgpu::Extent3d {
|
||||
width: sc_desc.width,
|
||||
height: sc_desc.height,
|
||||
@ -97,17 +110,26 @@ impl Example {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
};
|
||||
|
||||
device.create_texture(multisampled_frame_descriptor).create_default_view()
|
||||
device
|
||||
.create_texture(multisampled_frame_descriptor)
|
||||
.create_default_view()
|
||||
}
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
println!("Press left/right arrow keys to change sample_count.");
|
||||
let sample_count = 4;
|
||||
|
||||
let vs_bytes = framework::load_glsl(include_str!("shader.vert"), framework::ShaderStage::Vertex);
|
||||
let fs_bytes = framework::load_glsl(include_str!("shader.frag"), framework::ShaderStage::Fragment);
|
||||
let vs_bytes =
|
||||
framework::load_glsl(include_str!("shader.vert"), framework::ShaderStage::Vertex);
|
||||
let fs_bytes = framework::load_glsl(
|
||||
include_str!("shader.frag"),
|
||||
framework::ShaderStage::Fragment,
|
||||
);
|
||||
let vs_module = device.create_shader_module(&vs_bytes);
|
||||
let fs_module = device.create_shader_module(&fs_bytes);
|
||||
|
||||
@ -115,13 +137,21 @@ impl framework::Example for Example {
|
||||
bind_group_layouts: &[],
|
||||
});
|
||||
|
||||
let pipeline = Example::create_pipeline(device, &sc_desc, &vs_module, &fs_module, &pipeline_layout, sample_count);
|
||||
let multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, sample_count);
|
||||
let pipeline = Example::create_pipeline(
|
||||
device,
|
||||
&sc_desc,
|
||||
&vs_module,
|
||||
&fs_module,
|
||||
&pipeline_layout,
|
||||
sample_count,
|
||||
);
|
||||
let multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, sc_desc, sample_count);
|
||||
|
||||
let mut vertex_data = vec!();
|
||||
let mut vertex_data = vec![];
|
||||
|
||||
let max = 50;
|
||||
for i in 0..max {
|
||||
for i in 0 .. max {
|
||||
let percent = i as f32 / max as f32;
|
||||
let (sin, cos) = (percent * 2.0 * std::f32::consts::PI).sin_cos();
|
||||
vertex_data.push(Vertex {
|
||||
@ -134,9 +164,8 @@ impl framework::Example for Example {
|
||||
});
|
||||
}
|
||||
|
||||
let vertex_buffer = device
|
||||
.create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX)
|
||||
.fill_from_slice(&vertex_data);
|
||||
let vertex_buffer =
|
||||
device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX);
|
||||
let vertex_count = vertex_data.len() as u32;
|
||||
|
||||
let this = Example {
|
||||
@ -171,28 +200,46 @@ impl framework::Example for Example {
|
||||
self.rebuild_pipeline = true;
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> Option<wgpu::CommandBuffer> {
|
||||
self.sc_desc = sc_desc.clone();
|
||||
self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count);
|
||||
self.multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count);
|
||||
None
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
fn render(
|
||||
&mut self,
|
||||
frame: &wgpu::SwapChainOutput,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::CommandBuffer {
|
||||
if self.rebuild_pipeline {
|
||||
self.pipeline = Example::create_pipeline(device, &self.sc_desc, &self.vs_module, &self.fs_module, &self.pipeline_layout, self.sample_count);
|
||||
self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count);
|
||||
self.pipeline = Example::create_pipeline(
|
||||
device,
|
||||
&self.sc_desc,
|
||||
&self.vs_module,
|
||||
&self.fs_module,
|
||||
&self.pipeline_layout,
|
||||
self.sample_count,
|
||||
);
|
||||
self.multisampled_framebuffer =
|
||||
Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count);
|
||||
self.rebuild_pipeline = false;
|
||||
}
|
||||
|
||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
{
|
||||
let rpass_color_attachment = if self.sample_count == 1 {
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
@ -218,7 +265,7 @@ impl framework::Example for Example {
|
||||
});
|
||||
rpass.set_pipeline(&self.pipeline);
|
||||
rpass.set_vertex_buffers(0, &[(&self.vertex_buffer, 0)]);
|
||||
rpass.draw(0..self.vertex_count, 0..1);
|
||||
rpass.draw(0 .. self.vertex_count, 0 .. 1);
|
||||
}
|
||||
|
||||
encoder.finish()
|
||||
|
@ -3,8 +3,10 @@ use std::{mem, ops::Range, rc::Rc};
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
|
||||
struct Vertex {
|
||||
_pos: [i8; 4],
|
||||
@ -97,7 +99,7 @@ struct Light {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct LightRaw {
|
||||
proj: [[f32; 4]; 4],
|
||||
pos: [f32; 4],
|
||||
@ -116,24 +118,30 @@ impl Light {
|
||||
far: self.depth.end,
|
||||
};
|
||||
let mx_correction = framework::OPENGL_TO_WGPU_MATRIX;
|
||||
let mx_view_proj = mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
|
||||
let mx_view_proj =
|
||||
mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
|
||||
LightRaw {
|
||||
proj: *mx_view_proj.as_ref(),
|
||||
pos: [self.pos.x, self.pos.y, self.pos.z, 1.0],
|
||||
color: [self.color.r as f32, self.color.g as f32, self.color.b as f32, 1.0],
|
||||
color: [
|
||||
self.color.r as f32,
|
||||
self.color.g as f32,
|
||||
self.color.b as f32,
|
||||
1.0,
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct ForwardUniforms {
|
||||
proj: [[f32; 4]; 4],
|
||||
num_lights: [u32; 4],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)]
|
||||
#[derive(Clone, Copy, AsBytes, FromBytes)]
|
||||
struct EntityUniforms {
|
||||
model: [[f32; 4]; 4],
|
||||
color: [f32; 4],
|
||||
@ -183,30 +191,27 @@ impl Example {
|
||||
}
|
||||
|
||||
impl framework::Example for Example {
|
||||
fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
// Create the vertex and index buffers
|
||||
let vertex_size = mem::size_of::<Vertex>();
|
||||
let (cube_vertex_data, cube_index_data) = create_cube();
|
||||
let cube_vertex_buf = Rc::new(
|
||||
device
|
||||
.create_buffer_mapped(cube_vertex_data.len(), wgpu::BufferUsage::VERTEX)
|
||||
.fill_from_slice(&cube_vertex_data),
|
||||
device.create_buffer_with_data(cube_vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX),
|
||||
);
|
||||
|
||||
let cube_index_buf = Rc::new(
|
||||
device
|
||||
.create_buffer_mapped(cube_index_data.len(), wgpu::BufferUsage::INDEX)
|
||||
.fill_from_slice(&cube_index_data),
|
||||
device.create_buffer_with_data(cube_index_data.as_bytes(), wgpu::BufferUsage::INDEX),
|
||||
);
|
||||
|
||||
let (plane_vertex_data, plane_index_data) = create_plane(7);
|
||||
let plane_vertex_buf = device
|
||||
.create_buffer_mapped(plane_vertex_data.len(), wgpu::BufferUsage::VERTEX)
|
||||
.fill_from_slice(&plane_vertex_data);
|
||||
let plane_vertex_buf =
|
||||
device.create_buffer_with_data(plane_vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX);
|
||||
|
||||
let plane_index_buf = device
|
||||
.create_buffer_mapped(plane_index_data.len(), wgpu::BufferUsage::INDEX)
|
||||
.fill_from_slice(&plane_index_data);
|
||||
let plane_index_buf =
|
||||
device.create_buffer_with_data(plane_index_data.as_bytes(), wgpu::BufferUsage::INDEX);
|
||||
|
||||
let entity_uniform_size = mem::size_of::<EntityUniforms>() as wgpu::BufferAddress;
|
||||
let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
@ -214,15 +219,14 @@ impl framework::Example for Example {
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
});
|
||||
|
||||
let local_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
let local_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
],
|
||||
});
|
||||
}],
|
||||
});
|
||||
|
||||
let mut entities = vec![{
|
||||
use cgmath::SquareMatrix;
|
||||
@ -406,15 +410,14 @@ impl framework::Example for Example {
|
||||
|
||||
let shadow_pass = {
|
||||
// Create pipeline layout
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
],
|
||||
});
|
||||
}],
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],
|
||||
});
|
||||
@ -495,16 +498,12 @@ impl framework::Example for Example {
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
},
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
},
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
},
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 2,
|
||||
@ -531,12 +530,10 @@ impl framework::Example for Example {
|
||||
num_lights: [lights.len() as u32, 0, 0, 0],
|
||||
};
|
||||
let uniform_size = mem::size_of::<ForwardUniforms>() as wgpu::BufferAddress;
|
||||
let uniform_buf = device
|
||||
.create_buffer_mapped(
|
||||
1,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
.fill_from_slice(&[forward_uniforms]);
|
||||
let uniform_buf = device.create_buffer_with_data(
|
||||
forward_uniforms.as_bytes(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// Create bind group
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@ -654,13 +651,16 @@ impl framework::Example for Example {
|
||||
//empty
|
||||
}
|
||||
|
||||
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
|
||||
fn resize(
|
||||
&mut self,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
device: &wgpu::Device,
|
||||
) -> Option<wgpu::CommandBuffer> {
|
||||
let command_buf = {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(mx_ref);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
@ -686,30 +686,42 @@ impl framework::Example for Example {
|
||||
Some(command_buf)
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer {
|
||||
fn render(
|
||||
&mut self,
|
||||
frame: &wgpu::SwapChainOutput,
|
||||
device: &wgpu::Device,
|
||||
) -> wgpu::CommandBuffer {
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
{
|
||||
let size = mem::size_of::<EntityUniforms>() as wgpu::BufferAddress;
|
||||
let temp_buf_data =
|
||||
device.create_buffer_mapped(self.entities.len(), wgpu::BufferUsage::COPY_SRC);
|
||||
let size = mem::size_of::<EntityUniforms>();
|
||||
let temp_buf_data = device
|
||||
.create_buffer_mapped(self.entities.len() * size, wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
for (i, entity) in self.entities.iter_mut().enumerate() {
|
||||
// FIXME: Align and use `LayoutVerified`
|
||||
for (entity, slot) in self
|
||||
.entities
|
||||
.iter_mut()
|
||||
.zip(temp_buf_data.data.chunks_exact_mut(size))
|
||||
{
|
||||
if entity.rotation_speed != 0.0 {
|
||||
let rotation =
|
||||
cgmath::Matrix4::from_angle_x(cgmath::Deg(entity.rotation_speed));
|
||||
entity.mx_world = entity.mx_world * rotation;
|
||||
}
|
||||
temp_buf_data.data[i] = EntityUniforms {
|
||||
model: entity.mx_world.into(),
|
||||
color: [
|
||||
entity.color.r as f32,
|
||||
entity.color.g as f32,
|
||||
entity.color.b as f32,
|
||||
entity.color.a as f32,
|
||||
],
|
||||
};
|
||||
slot.copy_from_slice(
|
||||
EntityUniforms {
|
||||
model: entity.mx_world.into(),
|
||||
color: [
|
||||
entity.color.r as f32,
|
||||
entity.color.g as f32,
|
||||
entity.color.b as f32,
|
||||
entity.color.a as f32,
|
||||
],
|
||||
}
|
||||
.as_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
let temp_buf = temp_buf_data.finish();
|
||||
@ -717,28 +729,34 @@ impl framework::Example for Example {
|
||||
for (i, entity) in self.entities.iter().enumerate() {
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_buf,
|
||||
i as wgpu::BufferAddress * size,
|
||||
(i * size) as wgpu::BufferAddress,
|
||||
&entity.uniform_buf,
|
||||
0,
|
||||
size,
|
||||
size as wgpu::BufferAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if self.lights_are_dirty {
|
||||
self.lights_are_dirty = false;
|
||||
let size = (self.lights.len() * mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
||||
let size = mem::size_of::<LightRaw>();
|
||||
let total_size = size * self.lights.len();
|
||||
let temp_buf_data =
|
||||
device.create_buffer_mapped(self.lights.len(), wgpu::BufferUsage::COPY_SRC);
|
||||
for (i, light) in self.lights.iter().enumerate() {
|
||||
temp_buf_data.data[i] = light.to_raw();
|
||||
device.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC);
|
||||
// FIXME: Align and use `LayoutVerified`
|
||||
for (light, slot) in self
|
||||
.lights
|
||||
.iter()
|
||||
.zip(temp_buf_data.data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(light.to_raw().as_bytes());
|
||||
}
|
||||
encoder.copy_buffer_to_buffer(
|
||||
&temp_buf_data.finish(),
|
||||
0,
|
||||
&self.light_uniform_buf,
|
||||
0,
|
||||
size,
|
||||
total_size as wgpu::BufferAddress,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
#[path = "../framework.rs"]
|
||||
mod framework;
|
||||
|
||||
use zerocopy::AsBytes as _;
|
||||
|
||||
const SKYBOX_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm;
|
||||
|
||||
type Uniforms = [cgmath::Matrix4<f32>; 2];
|
||||
type Uniform = cgmath::Matrix4<f32>;
|
||||
type Uniforms = [Uniform; 2];
|
||||
|
||||
pub struct Skybox {
|
||||
aspect: f32,
|
||||
@ -26,6 +29,23 @@ impl Skybox {
|
||||
}
|
||||
}
|
||||
|
||||
fn buffer_from_uniforms(
|
||||
device: &wgpu::Device,
|
||||
uniforms: &Uniforms,
|
||||
usage: wgpu::BufferUsage,
|
||||
) -> wgpu::Buffer {
|
||||
let uniform_buf = device.create_buffer_mapped(std::mem::size_of::<Uniforms>(), usage);
|
||||
// FIXME: Align and use `LayoutVerified`
|
||||
for (u, slot) in uniforms.iter().zip(
|
||||
uniform_buf
|
||||
.data
|
||||
.chunks_exact_mut(std::mem::size_of::<Uniform>()),
|
||||
) {
|
||||
slot.copy_from_slice(AsRef::<[[f32; 4]; 4]>::as_ref(u).as_bytes());
|
||||
}
|
||||
uniform_buf.finish()
|
||||
}
|
||||
|
||||
impl framework::Example for Skybox {
|
||||
fn init(
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
@ -71,15 +91,11 @@ impl framework::Example for Skybox {
|
||||
|
||||
let aspect = sc_desc.width as f32 / sc_desc.height as f32;
|
||||
let uniforms = Self::generate_uniforms(aspect);
|
||||
let uniform_buf = device
|
||||
.create_buffer_mapped::<[[f32; 4]; 4]>(
|
||||
uniforms.len(),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
.fill_from_slice(&[
|
||||
uniforms[0].into(),
|
||||
uniforms[1].into(),
|
||||
]);
|
||||
let uniform_buf = buffer_from_uniforms(
|
||||
&device,
|
||||
&uniforms,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
let uniform_buf_size = std::mem::size_of::<Uniforms>();
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
@ -175,11 +191,11 @@ impl framework::Example for Skybox {
|
||||
for (i, image) in faces.iter().enumerate() {
|
||||
log::debug!(
|
||||
"Copying skybox image {} of size {},{} to gpu",
|
||||
i, image_width, image_height,
|
||||
i,
|
||||
image_width,
|
||||
image_height,
|
||||
);
|
||||
let image_buf = device
|
||||
.create_buffer_mapped(image.len(), wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(&image);
|
||||
let image_buf = device.create_buffer_with_data(image, wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
init_encoder.copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
@ -218,7 +234,7 @@ impl framework::Example for Skybox {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &uniform_buf,
|
||||
range: 0..uniform_buf_size as wgpu::BufferAddress,
|
||||
range: 0 .. uniform_buf_size as wgpu::BufferAddress,
|
||||
},
|
||||
},
|
||||
wgpu::Binding {
|
||||
@ -257,9 +273,8 @@ impl framework::Example for Skybox {
|
||||
let mx_total = uniforms[0] * uniforms[1];
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC)
|
||||
.fill_from_slice(mx_ref);
|
||||
let temp_buf =
|
||||
device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
let mut init_encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
@ -278,15 +293,7 @@ impl framework::Example for Skybox {
|
||||
let rotation = cgmath::Matrix4::<f32>::from_angle_x(cgmath::Deg(0.25));
|
||||
self.uniforms[1] = self.uniforms[1] * rotation;
|
||||
let uniform_buf_size = std::mem::size_of::<Uniforms>();
|
||||
let temp_buf = device
|
||||
.create_buffer_mapped::<[[f32; 4]; 4]>(
|
||||
self.uniforms.len(),
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
)
|
||||
.fill_from_slice(&[
|
||||
self.uniforms[0].into(),
|
||||
self.uniforms[1].into(),
|
||||
]);
|
||||
let temp_buf = buffer_from_uniforms(&device, &self.uniforms, wgpu::BufferUsage::COPY_SRC);
|
||||
|
||||
init_encoder.copy_buffer_to_buffer(
|
||||
&temp_buf,
|
||||
@ -315,7 +322,7 @@ impl framework::Example for Skybox {
|
||||
|
||||
rpass.set_pipeline(&self.pipeline);
|
||||
rpass.set_bind_group(0, &self.bind_group, &[]);
|
||||
rpass.draw(0..3 as u32, 0..1);
|
||||
rpass.draw(0 .. 3 as u32, 0 .. 1);
|
||||
}
|
||||
init_encoder.finish()
|
||||
}
|
||||
|
182
wgpu/src/lib.rs
182
wgpu/src/lib.rs
@ -1,9 +1,7 @@
|
||||
//! A cross-platform graphics and compute library based on WebGPU.
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use zerocopy::{AsBytes, FromBytes, LayoutVerified};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
use std::ops::Range;
|
||||
use std::ptr;
|
||||
@ -11,12 +9,10 @@ use std::slice;
|
||||
use std::thread;
|
||||
|
||||
pub use wgc::{
|
||||
binding_model::{
|
||||
ShaderStage,
|
||||
},
|
||||
binding_model::ShaderStage,
|
||||
command::{
|
||||
CommandEncoderDescriptor,
|
||||
CommandBufferDescriptor,
|
||||
CommandEncoderDescriptor,
|
||||
LoadOp,
|
||||
RenderPassDepthStencilAttachmentDescriptor,
|
||||
StoreOp,
|
||||
@ -50,6 +46,7 @@ pub use wgc::{
|
||||
VertexAttributeDescriptor,
|
||||
VertexFormat,
|
||||
},
|
||||
read_spirv,
|
||||
resource::{
|
||||
AddressMode,
|
||||
BufferDescriptor,
|
||||
@ -66,24 +63,18 @@ pub use wgc::{
|
||||
TextureViewDescriptor,
|
||||
TextureViewDimension,
|
||||
},
|
||||
swap_chain::{
|
||||
PresentMode,
|
||||
SwapChainDescriptor,
|
||||
},
|
||||
swap_chain::{PresentMode, SwapChainDescriptor},
|
||||
BufferAddress,
|
||||
Color,
|
||||
Extent3d,
|
||||
Origin3d,
|
||||
read_spirv,
|
||||
};
|
||||
|
||||
|
||||
//TODO: avoid heap allocating vectors during resource creation.
|
||||
#[derive(Default)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Default, Debug)]
|
||||
struct Temp {
|
||||
//bind_group_descriptors: Vec<wgn::BindGroupDescriptor>,
|
||||
//vertex_buffers: Vec<wgn::VertexBufferDescriptor>,
|
||||
//vertex_buffers: Vec<wgn::VertexBufferDescriptor>,
|
||||
}
|
||||
|
||||
/// A handle to a physical graphics and/or compute device.
|
||||
@ -500,27 +491,12 @@ impl<'a> TextureCopyView<'a> {
|
||||
}
|
||||
|
||||
/// A buffer being created, mapped in host memory.
|
||||
pub struct CreateBufferMapped<'a, T> {
|
||||
pub struct CreateBufferMapped<'a> {
|
||||
id: wgc::id::BufferId,
|
||||
pub data: &'a mut [T],
|
||||
pub data: &'a mut [u8],
|
||||
}
|
||||
|
||||
impl<'a, T> CreateBufferMapped<'a, T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Copies a slice into the mapped buffer and unmaps it, returning a [`Buffer`].
|
||||
///
|
||||
/// `slice` and `self.data` must have the same length.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the slices have different lengths.
|
||||
pub fn fill_from_slice(self, slice: &[T]) -> Buffer {
|
||||
self.data.copy_from_slice(slice);
|
||||
self.finish()
|
||||
}
|
||||
|
||||
impl CreateBufferMapped<'_> {
|
||||
/// Unmaps the buffer from host memory and returns a [`Buffer`].
|
||||
pub fn finish(self) -> Buffer {
|
||||
wgn::wgpu_buffer_unmap(self.id);
|
||||
@ -551,15 +527,21 @@ impl Adapter {
|
||||
///
|
||||
/// If no adapters are found that suffice all the "hard" options, `None` is returned.
|
||||
pub fn request(options: &RequestAdapterOptions, backends: BackendBit) -> Option<Self> {
|
||||
unsafe extern "C" fn adapter_callback(id: wgc::id::AdapterId, user_data: *mut std::ffi::c_void) {
|
||||
unsafe extern "C" fn adapter_callback(
|
||||
id: wgc::id::AdapterId,
|
||||
user_data: *mut std::ffi::c_void,
|
||||
) {
|
||||
*(user_data as *mut wgc::id::AdapterId) = id;
|
||||
}
|
||||
|
||||
let mut id = wgc::id::AdapterId::ERROR;
|
||||
wgn::wgpu_request_adapter_async(Some(options), backends, adapter_callback, &mut id as *mut _ as *mut std::ffi::c_void);
|
||||
Some(Adapter {
|
||||
id,
|
||||
})
|
||||
wgn::wgpu_request_adapter_async(
|
||||
Some(options),
|
||||
backends,
|
||||
adapter_callback,
|
||||
&mut id as *mut _ as *mut std::ffi::c_void,
|
||||
);
|
||||
Some(Adapter { id })
|
||||
}
|
||||
|
||||
/// Requests a connection to a physical device, creating a logical device.
|
||||
@ -617,7 +599,7 @@ impl Device {
|
||||
|
||||
let bindings = desc
|
||||
.bindings
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|binding| bm::BindGroupBinding {
|
||||
binding: binding.binding,
|
||||
resource: match binding.resource {
|
||||
@ -655,22 +637,27 @@ impl Device {
|
||||
pub fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> BindGroupLayout {
|
||||
use wgc::binding_model as bm;
|
||||
|
||||
let temp_layouts = desc.bindings
|
||||
let temp_layouts = desc
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|bind| bm::BindGroupLayoutBinding {
|
||||
binding: bind.binding,
|
||||
visibility: bind.visibility,
|
||||
ty: match bind.ty {
|
||||
BindingType::UniformBuffer { .. } => bm::BindingType::UniformBuffer,
|
||||
BindingType::StorageBuffer { readonly: false, .. } => bm::BindingType::StorageBuffer,
|
||||
BindingType::StorageBuffer { readonly: true, .. } => bm::BindingType::ReadonlyStorageBuffer,
|
||||
BindingType::StorageBuffer {
|
||||
readonly: false, ..
|
||||
} => bm::BindingType::StorageBuffer,
|
||||
BindingType::StorageBuffer { readonly: true, .. } => {
|
||||
bm::BindingType::ReadonlyStorageBuffer
|
||||
}
|
||||
BindingType::Sampler => bm::BindingType::Sampler,
|
||||
BindingType::SampledTexture { .. } => bm::BindingType::SampledTexture,
|
||||
BindingType::StorageTexture { .. } => bm::BindingType::StorageTexture,
|
||||
},
|
||||
dynamic: match bind.ty {
|
||||
BindingType::UniformBuffer { dynamic } |
|
||||
BindingType::StorageBuffer { dynamic, .. } => dynamic,
|
||||
BindingType::UniformBuffer { dynamic }
|
||||
| BindingType::StorageBuffer { dynamic, .. } => dynamic,
|
||||
_ => false,
|
||||
},
|
||||
multisampled: match bind.ty {
|
||||
@ -678,8 +665,8 @@ impl Device {
|
||||
_ => false,
|
||||
},
|
||||
texture_dimension: match bind.ty {
|
||||
BindingType::SampledTexture { dimension, .. } |
|
||||
BindingType::StorageTexture { dimension } => dimension,
|
||||
BindingType::SampledTexture { dimension, .. }
|
||||
| BindingType::StorageTexture { dimension } => dimension,
|
||||
_ => TextureViewDimension::D2,
|
||||
},
|
||||
})
|
||||
@ -756,7 +743,8 @@ impl Device {
|
||||
fragment_stage: fragment_stage
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |fs| fs as *const _),
|
||||
rasterization_state: desc.rasterization_state
|
||||
rasterization_state: desc
|
||||
.rasterization_state
|
||||
.as_ref()
|
||||
.map_or(ptr::null(), |p| p as *const _),
|
||||
primitive_topology: desc.primitive_topology,
|
||||
@ -808,32 +796,32 @@ impl Device {
|
||||
|
||||
/// Creates a new buffer and maps it into host-visible memory.
|
||||
///
|
||||
/// This returns a [`CreateBufferMapped<T>`], which exposes a `&mut [T]`. The actual [`Buffer`]
|
||||
/// This returns a [`CreateBufferMapped`], which exposes a `&mut [u8]`. The actual [`Buffer`]
|
||||
/// will not be created until calling [`CreateBufferMapped::finish`].
|
||||
pub fn create_buffer_mapped<'a, T>(
|
||||
&'a self,
|
||||
count: usize,
|
||||
usage: BufferUsage,
|
||||
) -> CreateBufferMapped<'a, T>
|
||||
where
|
||||
T: 'static + Copy + AsBytes + FromBytes,
|
||||
{
|
||||
let type_size = std::mem::size_of::<T>() as BufferAddress;
|
||||
assert_ne!(type_size, 0);
|
||||
pub fn create_buffer_mapped(&self, size: usize, usage: BufferUsage) -> CreateBufferMapped<'_> {
|
||||
assert_ne!(size, 0);
|
||||
|
||||
let desc = BufferDescriptor {
|
||||
size: (type_size * count as BufferAddress).max(1),
|
||||
size: size as BufferAddress,
|
||||
usage,
|
||||
};
|
||||
let mut ptr: *mut u8 = std::ptr::null_mut();
|
||||
|
||||
let id = wgn::wgpu_device_create_buffer_mapped(self.id, &desc, &mut ptr as *mut *mut u8);
|
||||
|
||||
let data = unsafe { std::slice::from_raw_parts_mut(ptr as *mut T, count) };
|
||||
let data = unsafe { std::slice::from_raw_parts_mut(ptr as *mut u8, size) };
|
||||
|
||||
CreateBufferMapped { id, data }
|
||||
}
|
||||
|
||||
/// Creates a new buffer, maps it into host-visible memory, copies data from the given slice,
|
||||
/// and finally unmaps it, returning a [`Buffer`].
|
||||
pub fn create_buffer_with_data(&self, data: &[u8], usage: BufferUsage) -> Buffer {
|
||||
let mapped = self.create_buffer_mapped(data.len(), usage);
|
||||
mapped.data.copy_from_slice(data);
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
/// Creates a new [`Texture`].
|
||||
///
|
||||
/// `desc` specifies the general format of the texture.
|
||||
@ -883,50 +871,39 @@ impl<T> Drop for BufferAsyncMapping<T> {
|
||||
}
|
||||
}
|
||||
|
||||
struct BufferMapReadAsyncUserData<T, F>
|
||||
struct BufferMapReadAsyncUserData<F>
|
||||
where
|
||||
T: FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
size: BufferAddress,
|
||||
size: usize,
|
||||
callback: F,
|
||||
buffer_id: wgc::id::BufferId,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
struct BufferMapWriteAsyncUserData<T, F>
|
||||
struct BufferMapWriteAsyncUserData<F>
|
||||
where
|
||||
T: AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
size: BufferAddress,
|
||||
size: usize,
|
||||
callback: F,
|
||||
buffer_id: wgc::id::BufferId,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn map_read_async<T, F>(&self, start: BufferAddress, count: usize, callback: F)
|
||||
pub fn map_read_async<F>(&self, start: BufferAddress, size: usize, callback: F)
|
||||
where
|
||||
T: 'static + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
extern "C" fn buffer_map_read_callback_wrapper<T, F>(
|
||||
extern "C" fn buffer_map_read_callback_wrapper<F>(
|
||||
status: BufferMapAsyncStatus,
|
||||
data: *const u8,
|
||||
user_data: *mut u8,
|
||||
) where
|
||||
T: FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
let user_data =
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapReadAsyncUserData<T, F>) };
|
||||
let data: &[u8] = unsafe {
|
||||
slice::from_raw_parts(data as *const u8, usize::try_from(user_data.size).unwrap())
|
||||
};
|
||||
let data = LayoutVerified::new_slice(data)
|
||||
.expect("could not interpret bytes as &[T]")
|
||||
.into_slice();
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapReadAsyncUserData<F>) };
|
||||
let data: &[u8] = unsafe { slice::from_raw_parts(data as *const u8, user_data.size) };
|
||||
match status {
|
||||
BufferMapAsyncStatus::Success => (user_data.callback)(Ok(BufferAsyncMapping {
|
||||
data,
|
||||
@ -936,44 +913,34 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
let size = (count * std::mem::size_of::<T>()) as BufferAddress;
|
||||
|
||||
let user_data = Box::new(BufferMapReadAsyncUserData {
|
||||
size,
|
||||
callback,
|
||||
buffer_id: self.id,
|
||||
phantom: std::marker::PhantomData,
|
||||
});
|
||||
wgn::wgpu_buffer_map_read_async(
|
||||
self.id,
|
||||
start,
|
||||
size,
|
||||
buffer_map_read_callback_wrapper::<T, F>,
|
||||
size as BufferAddress,
|
||||
buffer_map_read_callback_wrapper::<F>,
|
||||
Box::into_raw(user_data) as *mut u8,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn map_write_async<T, F>(&self, start: BufferAddress, count: usize, callback: F)
|
||||
pub fn map_write_async<F>(&self, start: BufferAddress, size: usize, callback: F)
|
||||
where
|
||||
T: 'static + AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
extern "C" fn buffer_map_write_callback_wrapper<T, F>(
|
||||
extern "C" fn buffer_map_write_callback_wrapper<F>(
|
||||
status: BufferMapAsyncStatus,
|
||||
data: *mut u8,
|
||||
user_data: *mut u8,
|
||||
) where
|
||||
T: AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
let user_data =
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapWriteAsyncUserData<T, F>) };
|
||||
let data = unsafe {
|
||||
slice::from_raw_parts_mut(data as *mut u8, usize::try_from(user_data.size).unwrap())
|
||||
};
|
||||
let data = LayoutVerified::new_slice(data)
|
||||
.expect("could not interpret bytes as &mut [T]")
|
||||
.into_mut_slice();
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapWriteAsyncUserData<F>) };
|
||||
let data = unsafe { slice::from_raw_parts_mut(data as *mut u8, user_data.size) };
|
||||
match status {
|
||||
BufferMapAsyncStatus::Success => (user_data.callback)(Ok(BufferAsyncMapping {
|
||||
data,
|
||||
@ -983,19 +950,16 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
let size = (count * std::mem::size_of::<T>()) as BufferAddress;
|
||||
|
||||
let user_data = Box::new(BufferMapWriteAsyncUserData {
|
||||
size,
|
||||
callback,
|
||||
buffer_id: self.id,
|
||||
phantom: std::marker::PhantomData,
|
||||
});
|
||||
wgn::wgpu_buffer_map_write_async(
|
||||
self.id,
|
||||
start,
|
||||
size,
|
||||
buffer_map_write_callback_wrapper::<T, F>,
|
||||
size as BufferAddress,
|
||||
buffer_map_write_callback_wrapper::<F>,
|
||||
Box::into_raw(user_data) as *mut u8,
|
||||
);
|
||||
}
|
||||
@ -1294,7 +1258,11 @@ impl<'a> RenderPass<'a> {
|
||||
///
|
||||
/// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
|
||||
/// vertex buffers can be set with [`RenderPass::set_vertex_buffers`].
|
||||
pub fn draw_indexed_indirect(&mut self, indirect_buffer: &Buffer, indirect_offset: BufferAddress) {
|
||||
pub fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
indirect_buffer: &Buffer,
|
||||
indirect_offset: BufferAddress,
|
||||
) {
|
||||
wgn::wgpu_render_pass_draw_indexed_indirect(self.id, indirect_buffer.id, indirect_offset);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
#[cfg(any(feature = "vulkan", feature = "metal", feature = "dx12"))]
|
||||
use std::convert::TryInto as _;
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "vulkan", feature = "metal", feature = "dx12"))]
|
||||
fn multithreaded_compute() {
|
||||
@ -13,14 +16,18 @@ fn multithreaded_compute() {
|
||||
thread::spawn(move || {
|
||||
let numbers = vec![100, 100, 100];
|
||||
|
||||
let size = (numbers.len() * std::mem::size_of::<u32>()) as wgpu::BufferAddress;
|
||||
let slice_size = numbers.len() * std::mem::size_of::<u32>();
|
||||
let size = slice_size as wgpu::BufferAddress;
|
||||
|
||||
let instance = wgpu::Instance::new();
|
||||
let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
});
|
||||
let adapter = wgpu::Adapter::request(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
},
|
||||
wgpu::BackendBit::PRIMARY,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut device = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
|
||||
extensions: wgpu::Extensions {
|
||||
anisotropic_filtering: false,
|
||||
},
|
||||
@ -28,16 +35,15 @@ fn multithreaded_compute() {
|
||||
});
|
||||
|
||||
let cs = include_bytes!("../examples/hello-compute/shader.comp.spv");
|
||||
let cs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap());
|
||||
let cs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap());
|
||||
|
||||
let staging_buffer = device
|
||||
.create_buffer_mapped(
|
||||
numbers.len(),
|
||||
wgpu::BufferUsage::MAP_READ
|
||||
| wgpu::BufferUsage::COPY_DST
|
||||
| wgpu::BufferUsage::COPY_SRC,
|
||||
)
|
||||
.fill_from_slice(&numbers);
|
||||
let staging_buffer = device.create_buffer_with_data(
|
||||
numbers.as_slice(),
|
||||
wgpu::BufferUsage::MAP_READ
|
||||
| wgpu::BufferUsage::COPY_DST
|
||||
| wgpu::BufferUsage::COPY_SRC,
|
||||
);
|
||||
|
||||
let storage_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size,
|
||||
@ -48,16 +54,14 @@ fn multithreaded_compute() {
|
||||
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
readonly: false,
|
||||
},
|
||||
bindings: &[wgpu::BindGroupLayoutBinding {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
readonly: false,
|
||||
},
|
||||
],
|
||||
}],
|
||||
});
|
||||
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@ -95,10 +99,17 @@ fn multithreaded_compute() {
|
||||
}
|
||||
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
|
||||
|
||||
device.get_queue().submit(&[encoder.finish()]);
|
||||
queue.submit(&[encoder.finish()]);
|
||||
|
||||
staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u32]>| {
|
||||
assert_eq!(result.unwrap().data, [25, 25, 25]);
|
||||
// FIXME: Align and use `LayoutVerified`
|
||||
staging_buffer.map_read_async(0, slice_size, |result| {
|
||||
let result_data: Box<[u32]> = result
|
||||
.unwrap()
|
||||
.data
|
||||
.chunks_exact(std::mem::size_of::<u32>())
|
||||
.map(|c| u32::from_ne_bytes(c.try_into().unwrap()))
|
||||
.collect();
|
||||
assert_eq!(&*result_data, &[25, 25, 25]);
|
||||
});
|
||||
tx.send(true).unwrap();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user