migrated framework

pull/90/head
Ben Hansen 4 years ago
parent 4186d5af45
commit b4a51e66a4

5
Cargo.lock generated

@ -604,14 +604,15 @@ dependencies = [
"anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
"bytemuck 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fs_extra 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.7 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"shaderc 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tobj 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wgpu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

@ -8,19 +8,18 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
bytemuck = "1.3"
image = "0.23"
failure = "0.1"
bytemuck = "1.4"
cgmath = "0.17"
env_logger = "0.7"
futures = "0.3"
tobj = "2"
image = "0.23"
log = "0.4"
tobj = "2.0"
wgpu = "0.6"
winit = "0.22"
wgpu = "0.5"
[dependencies.cgmath]
version = "0.17"
features = ["swizzle"]
[build-dependencies]
fs_extra = "1.1"
anyhow = "1.0"
fs_extra = "1.2"
glob = "0.3"
shaderc = "0.6"

@ -1,4 +1,5 @@
use std::mem;
use wgpu::util::{DeviceExt, BufferInitDescriptor};
pub trait ToRaw {
type Output;
@ -21,9 +22,12 @@ impl<R: Copy + bytemuck::Pod + bytemuck::Zeroable> RawBuffer<R> {
pub fn from_vec(device: &wgpu::Device, data: Vec<R>, usage: wgpu::BufferUsage) -> Self {
let buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&data),
usage,
let buffer = device.create_buffer_init(
&BufferInitDescriptor {
contents: bytemuck::cast_slice(&data),
usage,
label: None,
}
);
Self::from_parts(buffer, data, usage)
}
@ -62,6 +66,7 @@ impl<U: ToRaw<Output=R>, R: Copy + bytemuck::Pod + bytemuck::Zeroable> Buffer<U,
size: buffer_size,
usage,
label: None,
mapped_at_creation: false,
});
let raw_buffer = RawBuffer::from_parts(buffer, Vec::new(), usage);
Self::from_parts(Vec::new(), raw_buffer, usage)

@ -16,6 +16,7 @@ pub use texture::*;
use anyhow::*;
use cgmath::*;
use std::time::{Duration, Instant};
use wgpu::util::{BufferInitDescriptor, DeviceExt};
use winit::event::*;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};
@ -32,15 +33,22 @@ pub struct Display {
impl Display {
pub async fn new(window: &Window) -> Result<Self, Error> {
let size = window.inner_size();
let surface = wgpu::Surface::create(window);
let _adapter: wgpu::Adapter = wgpu::Adapter::request(
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
let surface = unsafe { instance.create_surface(window) };
let _adapter = instance.request_adapter(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
compatible_surface: Some(&surface),
},
wgpu::BackendBit::PRIMARY,
).await.context("Unable to find valid device!")?;
let (device, queue) = _adapter.request_device(&Default::default()).await;
).await.unwrap();
let (device, queue) = _adapter.request_device(
&wgpu::DeviceDescriptor {
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: true,
},
None,
).await.unwrap();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
@ -92,9 +100,12 @@ impl Uniforms {
view_position: Zero::zero(),
view_proj: cgmath::Matrix4::identity(),
};
let buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&[data]),
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
let buffer = device.create_buffer_init(
&BufferInitDescriptor {
label: Some("Uniform Buffer"),
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
}
);
Self { data, buffer }
@ -106,9 +117,12 @@ impl Uniforms {
}
pub fn update_buffer(&self, device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder) {
let staging_buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&[self.data]),
wgpu::BufferUsage::COPY_SRC,
let staging_buffer = device.create_buffer_init(
&BufferInitDescriptor {
label: Some("Uniform Update Buffer"),
contents: bytemuck::cast_slice(&[self.data]),
usage: wgpu::BufferUsage::COPY_SRC,
}
);
encoder.copy_buffer_to_buffer(
&staging_buffer,
@ -133,11 +147,15 @@ impl UniformBinding {
pub fn new(device: &wgpu::Device, uniforms: &Uniforms) -> Self {
let layout = device.create_bind_group_layout(
&wgpu::BindGroupLayoutDescriptor {
bindings: &[
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
ty: wgpu::BindingType::UniformBuffer {
dynamic: false,
min_binding_size: None,
},
count: None,
},
],
label: Some("UniformBinding::layout"),
@ -146,13 +164,10 @@ impl UniformBinding {
let bind_group = device.create_bind_group(
&wgpu::BindGroupDescriptor {
layout: &layout,
bindings: &[
wgpu::Binding {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniforms.buffer,
range: 0..std::mem::size_of_val(&uniforms.data) as _,
},
resource: wgpu::BindingResource::Buffer(uniforms.buffer.slice(..)),
},
],
label: Some("UniformBinding::bind_group")
@ -166,13 +181,10 @@ impl UniformBinding {
self.bind_group = device.create_bind_group(
&wgpu::BindGroupDescriptor {
layout: &self.layout,
bindings: &[
wgpu::Binding {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniforms.buffer,
range: 0..std::mem::size_of_val(&uniforms) as wgpu::BufferAddress,
},
resource: wgpu::BindingResource::Buffer(uniforms.buffer.slice(..))
},
],
label: Some("UniformBinding::bind_group")

@ -1,4 +1,5 @@
use cgmath::*;
use wgpu::util::{BufferInitDescriptor, DeviceExt};
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@ -21,9 +22,12 @@ impl Light {
position: Vector4::new(position.x, position.y, position.z, 1.0),
color: Vector4::new(color.x, color.y, color.z, 1.0),
};
let buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&[data]),
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
let buffer = device.create_buffer_init(
&BufferInitDescriptor {
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
label: Some("Light Buffer"),
}
);
Self { data, buffer }

@ -1,6 +1,7 @@
use anyhow::*;
use std::ops::Range;
use std::path::Path;
use anyhow::*;
use wgpu::util::DeviceExt;
use crate::texture;
@ -76,20 +77,20 @@ impl<'a> Material<'a> {
) -> Self {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout,
bindings: &[
wgpu::Binding {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
},
wgpu::Binding {
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
},
wgpu::Binding {
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::TextureView(&normal_texture.view),
},
wgpu::Binding {
wgpu::BindGroupEntry {
binding: 3,
resource: wgpu::BindingResource::Sampler(&normal_texture.sampler),
},
@ -122,34 +123,27 @@ pub struct Model<'a> {
impl<'a> Model<'a> {
pub fn load<P: AsRef<Path>>(
device: &wgpu::Device,
queue: &wgpu::Queue,
layout: &wgpu::BindGroupLayout,
path: P,
) -> Result<(Self, Vec<wgpu::CommandBuffer>)> {
) -> Result<Self> {
let (obj_models, obj_materials) = tobj::load_obj(path.as_ref(), true)?;
// We're assuming that the texture files are stored with the obj file
let containing_folder = path.as_ref()
.parent()
.context("Unable to find parent for model")?;
// Our `Texure` struct currently returns a `CommandBuffer` when it's created so we need to collect those and return them.
let mut command_buffers = Vec::new();
let containing_folder = path.as_ref().parent()
.context("Directory has no parent")?;
let mut materials = Vec::new();
for mat in obj_materials {
let name = mat.name;
let diffuse_path = mat.diffuse_texture;
let (diffuse_texture, cmds) = texture::Texture::load(device, containing_folder.join(diffuse_path), false)?;
command_buffers.push(cmds);
let diffuse_texture = texture::Texture::load(device, queue, containing_folder.join(diffuse_path), false)?;
let normal_path = mat.unknown_param.get("map_Bump")
.with_context(|| format!("No normal map specified for {}", name))?;
let (normal_texture, cmds) = texture::Texture::load(device, containing_folder.join(normal_path), true)?;
command_buffers.push(cmds);
let normal_path = mat.normal_texture;
let normal_texture = texture::Texture::load(device, queue, containing_folder.join(normal_path), true)?;
materials.push(Material::new(
device,
&name,
&mat.name,
diffuse_texture,
normal_texture,
layout,
@ -228,14 +222,19 @@ impl<'a> Model<'a> {
vertices[c[2] as usize].bitangent = bitangent;
}
let vertex_buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&vertices),
wgpu::BufferUsage::VERTEX,
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,
}
);
let index_buffer = device.create_buffer_with_data(
bytemuck::cast_slice(indices),
wgpu::BufferUsage::INDEX,
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,
}
);
meshes.push(Mesh {
@ -247,7 +246,7 @@ impl<'a> Model<'a> {
});
}
Ok((Self { meshes, materials }, command_buffers))
Ok(Self { meshes, materials })
}
}
@ -316,8 +315,8 @@ where
uniforms: &'b wgpu::BindGroup,
light: &'b wgpu::BindGroup,
) {
self.set_vertex_buffer(0, &mesh.vertex_buffer, 0, 0);
self.set_index_buffer(&mesh.index_buffer, 0, 0);
self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
self.set_index_buffer(mesh.index_buffer.slice(..));
self.set_bind_group(0, &material.bind_group, &[]);
self.set_bind_group(1, &uniforms, &[]);
self.set_bind_group(2, &light, &[]);
@ -414,8 +413,8 @@ where
uniforms: &'b wgpu::BindGroup,
light: &'b wgpu::BindGroup,
) {
self.set_vertex_buffer(0, &mesh.vertex_buffer, 0, 0);
self.set_index_buffer(&mesh.index_buffer, 0, 0);
self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
self.set_index_buffer(mesh.index_buffer.slice(..));
self.set_bind_group(0, uniforms, &[]);
self.set_bind_group(1, light, &[]);
self.draw_indexed(0..mesh.num_elements, 0, instances);
@ -441,9 +440,3 @@ where
}
}
}
pub struct ModelPass {
pipeline: wgpu::RenderPipeline,
// uniforms:
}

@ -3,8 +3,8 @@ use crate::model::Vertex;
pub struct RenderPipelineBuilder<'a> {
layout: Option<&'a wgpu::PipelineLayout>,
vertex_shader: Option<&'a [u8]>,
fragment_shader: Option<&'a [u8]>,
vertex_shader: Option<wgpu::ShaderModuleSource<'a>>,
fragment_shader: Option<wgpu::ShaderModuleSource<'a>>,
front_face: wgpu::FrontFace,
cull_mode: wgpu::CullMode,
depth_bias: i32,
@ -47,13 +47,13 @@ impl<'a> RenderPipelineBuilder<'a> {
self
}
pub fn vertex_shader(&mut self, spv: &'a [u8]) -> &mut Self {
self.vertex_shader = Some(spv);
pub fn vertex_shader(&mut self, src: wgpu::ShaderModuleSource<'a>) -> &mut Self {
self.vertex_shader = Some(src);
self
}
pub fn fragment_shader(&mut self, spv: &'a [u8]) -> &mut Self {
self.fragment_shader = Some(spv);
pub fn fragment_shader(&mut self, src: wgpu::ShaderModuleSource<'a>) -> &mut Self {
self.fragment_shader = Some(src);
self
}
@ -128,10 +128,7 @@ impl<'a> RenderPipelineBuilder<'a> {
format,
depth_write_enabled,
depth_compare,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
stencil: Default::default(),
}
)
}
@ -175,7 +172,7 @@ impl<'a> RenderPipelineBuilder<'a> {
self
}
pub fn build(&self, device: &wgpu::Device) -> Result<wgpu::RenderPipeline> {
pub fn build(&mut self, device: &wgpu::Device) -> Result<wgpu::RenderPipeline> {
// We need a layout
if self.layout.is_none() {
bail!("No pipeline layout supplied!");
@ -193,18 +190,19 @@ impl<'a> RenderPipelineBuilder<'a> {
if self.vertex_shader.is_none() {
bail!("No vertex shader supplied!")
}
let vs = create_shader_module(device, self.vertex_shader.context("Please include a vertex shader")?);
let vs = create_shader_module(device, self.vertex_shader.take().context("Please include a vertex shader")?);
// The fragment shader is optional (IDK why, but it is).
// Having the shader be optional is giving me issues with
// the borrow checker so I'm going to use a default shader
// if the user doesn't supply one.
let fs_spv = self.fragment_shader.context("Please include a fragment shader")?;
let fs_spv = self.fragment_shader.take().context("Please include a fragment shader")?;
let fs = create_shader_module(device, fs_spv);
let pipeline = device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
layout: &layout,
label: Some("Render Pipeline"),
layout: Some(&layout),
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs,
entry_point: "main",
@ -221,6 +219,7 @@ impl<'a> RenderPipelineBuilder<'a> {
depth_bias: self.depth_bias,
depth_bias_slope_scale: self.depth_bias_slope_scale,
depth_bias_clamp: self.depth_bias_clamp,
clamp_depth: false,
}),
primitive_topology: self.primitive_topology,
color_states: &self.color_states,
@ -239,12 +238,6 @@ impl<'a> RenderPipelineBuilder<'a> {
}
fn create_shader_module(device: &wgpu::Device, spirv: &[u8]) -> wgpu::ShaderModule {
device.create_shader_module(
&wgpu::read_spirv(
std::io::Cursor::new(
spirv
)
).unwrap()
)
fn create_shader_module(device: &wgpu::Device, spirv: wgpu::ShaderModuleSource) -> wgpu::ShaderModule {
device.create_shader_module(spirv)
}

@ -18,20 +18,23 @@ impl<'a> Texture<'a> {
pub fn load<P: AsRef<Path>>(
device: &wgpu::Device,
queue: &wgpu::Queue,
path: P,
is_normal_map: bool,
) -> Result<(Self, wgpu::CommandBuffer)> {
) -> Result<Self> {
let path_copy = path.as_ref().to_path_buf();
let label = path_copy.to_str().unwrap();
let img = image::open(path)?;
Self::from_image(device, &img, is_normal_map)
Self::from_image(device, queue, &img, Some(label), is_normal_map)
}
pub fn from_descriptor(
device: &wgpu::Device,
device: &wgpu::Device,
desc: wgpu::TextureDescriptor<'a>
) -> Self {
let texture = device.create_texture(&desc);
let view = texture.create_default_view();
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
@ -41,7 +44,8 @@ impl<'a> Texture<'a> {
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_max_clamp: 100.0,
compare: wgpu::CompareFunction::LessEqual,
compare: Some(wgpu::CompareFunction::LessEqual),
..Default::default()
});
Self { texture, view, sampler, desc }
@ -49,18 +53,22 @@ impl<'a> Texture<'a> {
pub fn from_bytes(
device: &wgpu::Device,
queue: &wgpu::Queue,
label: Option<&str>,
is_normal_map: bool,
bytes: &[u8],
) -> Result<(Self, wgpu::CommandBuffer)> {
) -> Result<Self> {
let img = image::load_from_memory(bytes)?;
Self::from_image(device, &img, is_normal_map)
Self::from_image(device, queue, &img, label, is_normal_map)
}
pub fn from_image(
device: &wgpu::Device,
queue: &wgpu::Queue,
img: &image::DynamicImage,
_label: Option<&str>,
is_normal_map: bool,
) -> Result<(Self, wgpu::CommandBuffer)> {
) -> Result<Self> {
let rgba = img.to_rgba();
let dimensions = img.dimensions();
@ -71,7 +79,6 @@ impl<'a> Texture<'a> {
};
let desc = wgpu::TextureDescriptor {
size,
array_layer_count: 1,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
@ -85,34 +92,22 @@ impl<'a> Texture<'a> {
};
let texture = device.create_texture(&desc);
let buffer = device.create_buffer_with_data(
&rgba,
wgpu::BufferUsage::COPY_SRC,
);
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: None,
});
encoder.copy_buffer_to_texture(
wgpu::BufferCopyView {
buffer: &buffer,
offset: 0,
bytes_per_row: 4 * dimensions.0,
rows_per_image: dimensions.1,
},
queue.write_texture(
wgpu::TextureCopyView {
texture: &texture,
mip_level: 0,
array_layer: 0,
origin: wgpu::Origin3d::ZERO,
},
},
&rgba,
wgpu::TextureDataLayout {
offset: 0,
bytes_per_row: 4 * dimensions.0,
rows_per_image: dimensions.1,
},
size,
);
let cmd_buffer = encoder.finish();
let view = texture.create_default_view();
let view = texture.create_view(&Default::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
@ -122,10 +117,11 @@ impl<'a> Texture<'a> {
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_max_clamp: 100.0,
compare: wgpu::CompareFunction::Always,
compare: Some(wgpu::CompareFunction::Always),
..Default::default()
});
Ok((Self { texture, view, sampler, desc }, cmd_buffer))
Ok(Self { texture, view, sampler, desc })
}
pub fn create_depth_texture(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self {
@ -136,7 +132,6 @@ impl<'a> Texture<'a> {
height: sc_desc.height,
depth: 1,
},
array_layer_count: 1,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
@ -155,6 +150,7 @@ impl<'a> Texture<'a> {
size: buffer_size as wgpu::BufferAddress,
usage: buffer_usage,
label: None,
mapped_at_creation: false,
};
let buffer = device.create_buffer(&buffer_desc);

Loading…
Cancel
Save