mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Update with minBufferBindingSize
This commit is contained in:
@@ -28,14 +28,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
|
||||
package = "wgpu-core"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "d1deae5747f5bd0a6503c1462555f201eaae02c9"
|
||||
rev = "fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
features = ["raw-window-handle"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
version = "0.5"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "d1deae5747f5bd0a6503c1462555f201eaae02c9"
|
||||
rev = "fc2dd481b2713cd0eda6ffa540faeaf7418fd051"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
|
||||
@@ -48,35 +48,60 @@ impl framework::Example for Example {
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap());
|
||||
|
||||
// buffer for simulation parameters uniform
|
||||
|
||||
let sim_param_data = [
|
||||
0.04f32, // deltaT
|
||||
0.1, // rule1Distance
|
||||
0.025, // rule2Distance
|
||||
0.025, // rule3Distance
|
||||
0.02, // rule1Scale
|
||||
0.05, // rule2Scale
|
||||
0.005, // rule3Scale
|
||||
]
|
||||
.to_vec();
|
||||
let sim_param_buffer = device.create_buffer_with_data(
|
||||
bytemuck::cast_slice(&sim_param_data),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// create compute bind layout group and compute pipeline layout
|
||||
|
||||
let compute_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::COMPUTE,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(
|
||||
sim_param_data.len() as _
|
||||
),
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::COMPUTE,
|
||||
wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(
|
||||
(NUM_PARTICLES * 16) as _,
|
||||
),
|
||||
readonly: false,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::COMPUTE,
|
||||
wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(
|
||||
(NUM_PARTICLES * 16) as _,
|
||||
),
|
||||
readonly: false,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
label: None,
|
||||
});
|
||||
@@ -155,23 +180,6 @@ impl framework::Example for Example {
|
||||
wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// buffer for simulation parameters uniform
|
||||
|
||||
let sim_param_data = [
|
||||
0.04f32, // deltaT
|
||||
0.1, // rule1Distance
|
||||
0.025, // rule2Distance
|
||||
0.025, // rule3Distance
|
||||
0.02, // rule1Scale
|
||||
0.05, // rule2Scale
|
||||
0.005, // rule3Scale
|
||||
]
|
||||
.to_vec();
|
||||
let sim_param_buffer = device.create_buffer_with_data(
|
||||
bytemuck::cast_slice(&sim_param_data),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
// buffer for all particles data of type [(posx,posy,velx,vely),...]
|
||||
|
||||
let mut initial_particle_data = vec![0.0f32; (4 * NUM_PARTICLES) as usize];
|
||||
|
||||
@@ -135,28 +135,28 @@ impl framework::Example for Example {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(64),
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
@@ -198,7 +198,6 @@ impl framework::Example for Example {
|
||||
|
||||
// Create other resources
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
|
||||
@@ -65,15 +65,15 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
bindings: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::COMPUTE,
|
||||
ty: wgpu::BindingType::StorageBuffer {
|
||||
bindings: &[wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::COMPUTE,
|
||||
wgpu::BindingType::StorageBuffer {
|
||||
dynamic: false,
|
||||
readonly: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(4),
|
||||
},
|
||||
..Default::default()
|
||||
}],
|
||||
)],
|
||||
});
|
||||
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
@@ -154,12 +154,6 @@ fn main() {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_compute_0() {
|
||||
let input = vec![];
|
||||
futures::executor::block_on(assert_execute_gpu(input, vec![]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compute_1() {
|
||||
let input = vec![1, 2, 3, 4];
|
||||
|
||||
@@ -84,22 +84,20 @@ impl Example {
|
||||
) {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
label: None,
|
||||
});
|
||||
@@ -229,28 +227,28 @@ impl framework::Example for Example {
|
||||
// Create pipeline layout
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(64),
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
multisampled: false,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
label: None,
|
||||
});
|
||||
|
||||
@@ -244,12 +244,18 @@ impl framework::Example for Example {
|
||||
|
||||
let local_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
}],
|
||||
bindings: &[wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(mem::size_of::<
|
||||
EntityUniforms,
|
||||
>(
|
||||
)
|
||||
as _),
|
||||
},
|
||||
)],
|
||||
label: None,
|
||||
});
|
||||
|
||||
@@ -424,22 +430,24 @@ impl framework::Example for Example {
|
||||
};
|
||||
|
||||
let shadow_pass = {
|
||||
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
||||
// Create pipeline layout
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
}],
|
||||
bindings: &[wgpu::BindGroupLayoutEntry::new(
|
||||
0, // global
|
||||
wgpu::ShaderStage::VERTEX,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(uniform_size),
|
||||
},
|
||||
)],
|
||||
label: None,
|
||||
});
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],
|
||||
});
|
||||
|
||||
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
||||
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: uniform_size,
|
||||
@@ -516,34 +524,42 @@ impl framework::Example for Example {
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1, // lights
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0, // global
|
||||
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(mem::size_of::<
|
||||
ForwardUniforms,
|
||||
>(
|
||||
)
|
||||
as _),
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1, // lights
|
||||
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(
|
||||
light_uniform_size,
|
||||
),
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2Array,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: true },
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
3,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: true },
|
||||
),
|
||||
],
|
||||
label: None,
|
||||
});
|
||||
|
||||
@@ -42,28 +42,28 @@ impl framework::Example for Skybox {
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
multisampled: false,
|
||||
dimension: wgpu::TextureViewDimension::Cube,
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
label: None,
|
||||
});
|
||||
|
||||
@@ -144,12 +144,14 @@ impl framework::Example for Example {
|
||||
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
..wgpu::BindGroupLayoutEntry::default()
|
||||
}],
|
||||
bindings: &[wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
)],
|
||||
label: Some("uniform workaround bind group layout"),
|
||||
});
|
||||
|
||||
@@ -248,26 +250,26 @@ impl framework::Example for Example {
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor::default());
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("bind group layout"),
|
||||
bindings: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: Some(2),
|
||||
..Default::default()
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
..Default::default()
|
||||
..wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
label: Some("bind group layout"),
|
||||
});
|
||||
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
|
||||
@@ -4,7 +4,7 @@ mod framework;
|
||||
mod point_gen;
|
||||
|
||||
use cgmath::Point3;
|
||||
|
||||
use std::{io, mem};
|
||||
use wgpu::vertex_attr_array;
|
||||
|
||||
///
|
||||
@@ -21,7 +21,11 @@ const SIZE: f32 = 10.0;
|
||||
/// Location of the camera.
|
||||
/// Location of light is in terrain/water shaders.
|
||||
///
|
||||
const CAMERA: Point3<f32> = Point3 { x: -100.0, y: 50.0, z: 100.0 };
|
||||
const CAMERA: Point3<f32> = Point3 {
|
||||
x: -100.0,
|
||||
y: 50.0,
|
||||
z: 100.0,
|
||||
};
|
||||
|
||||
struct Matrices {
|
||||
view: cgmath::Matrix4<f32>,
|
||||
@@ -45,7 +49,7 @@ struct WaterUniforms {
|
||||
view: [f32; 16],
|
||||
projection: [f32; 16],
|
||||
time_size_width: [f32; 4],
|
||||
height: f32,
|
||||
height: [f32; 4],
|
||||
}
|
||||
|
||||
struct Uniforms {
|
||||
@@ -103,7 +107,7 @@ impl Example {
|
||||
let reg_view = cgmath::Matrix4::look_at(
|
||||
CAMERA,
|
||||
cgmath::Point3::new(0f32, 0.0, 0.0),
|
||||
cgmath::Vector3::unit_y(), //Note that y is up. Differs from other examples.
|
||||
cgmath::Vector3::unit_y(), //Note that y is up. Differs from other examples.
|
||||
);
|
||||
|
||||
let scale = cgmath::Matrix4::from_nonuniform_scale(8.0, 1.5, 8.0);
|
||||
@@ -116,7 +120,6 @@ impl Example {
|
||||
cgmath::Vector3::unit_y(),
|
||||
);
|
||||
|
||||
|
||||
let correction = framework::OPENGL_TO_WGPU_MATRIX;
|
||||
|
||||
let flipped_view = flipped_view * scale;
|
||||
@@ -132,7 +135,7 @@ impl Example {
|
||||
let Matrices {
|
||||
view,
|
||||
flipped_view,
|
||||
projection
|
||||
projection,
|
||||
} = Self::generate_matrices(width as f32 / height as f32);
|
||||
|
||||
Uniforms {
|
||||
@@ -148,8 +151,8 @@ impl Example {
|
||||
view: *view.as_ref(),
|
||||
projection: *projection.as_ref(),
|
||||
time_size_width: [0.0, 1.0, SIZE * 2.0, width as f32],
|
||||
height: height as f32
|
||||
}
|
||||
height: [height as f32, 0.0, 0.0, 0.0],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +177,16 @@ impl Example {
|
||||
} = Self::generate_uniforms(sc_desc.width, sc_desc.height);
|
||||
|
||||
// Put the uniforms into buffers on the GPU
|
||||
queue.write_buffer(terrain_normal_uniforms, 0, bytemuck::cast_slice(&[terrain_normal]));
|
||||
queue.write_buffer(terrain_flipped_uniforms, 0, bytemuck::cast_slice(&[terrain_flipped]));
|
||||
queue.write_buffer(
|
||||
terrain_normal_uniforms,
|
||||
0,
|
||||
bytemuck::cast_slice(&[terrain_normal]),
|
||||
);
|
||||
queue.write_buffer(
|
||||
terrain_flipped_uniforms,
|
||||
0,
|
||||
bytemuck::cast_slice(&[terrain_flipped]),
|
||||
);
|
||||
queue.write_buffer(water_uniforms, 0, bytemuck::cast_slice(&[water]));
|
||||
|
||||
let texture_extent = wgpu::Extent3d {
|
||||
@@ -191,7 +202,9 @@ impl Example {
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: sc_desc.format,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
usage: wgpu::TextureUsage::SAMPLED
|
||||
| wgpu::TextureUsage::COPY_DST
|
||||
| wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
let draw_depth_buffer = device.create_texture(&wgpu::TextureDescriptor {
|
||||
@@ -201,7 +214,9 @@ impl Example {
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth32Float,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
usage: wgpu::TextureUsage::SAMPLED
|
||||
| wgpu::TextureUsage::COPY_DST
|
||||
| wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
@@ -224,11 +239,15 @@ impl Example {
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::TextureView(&reflection_texture.create_default_view()),
|
||||
resource: wgpu::BindingResource::TextureView(
|
||||
&reflection_texture.create_default_view(),
|
||||
),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::TextureView(&draw_depth_buffer.create_default_view())
|
||||
resource: wgpu::BindingResource::TextureView(
|
||||
&draw_depth_buffer.create_default_view(),
|
||||
),
|
||||
},
|
||||
wgpu::Binding {
|
||||
binding: 3,
|
||||
@@ -238,7 +257,11 @@ impl Example {
|
||||
label: Some("Water Bind Group"),
|
||||
});
|
||||
|
||||
(reflection_texture.create_default_view(), draw_depth_buffer.create_default_view(), water_bind_group)
|
||||
(
|
||||
reflection_texture.create_default_view(),
|
||||
draw_depth_buffer.create_default_view(),
|
||||
water_bind_group,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,8 +271,6 @@ impl framework::Example for Example {
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
) -> (Self, Option<wgpu::CommandBuffer>) {
|
||||
use std::mem;
|
||||
|
||||
// Size of one water vertex
|
||||
let water_vertex_size = mem::size_of::<point_gen::WaterVertexAttributes>();
|
||||
|
||||
@@ -265,48 +286,53 @@ impl framework::Example for Example {
|
||||
let mut terrain_random = rand::thread_rng();
|
||||
|
||||
// Generate terrain. The closure determines what each hexagon will look like.
|
||||
let terrain = point_gen::HexTerrainMesh::generate(SIZE, |point| -> point_gen::TerrainVertex {
|
||||
use rand::Rng;
|
||||
use noise::NoiseFn;
|
||||
let noise = terrain_noise.get([point[0] as f64 / 5.0, point[1] as f64 / 5.0]) + 0.1;
|
||||
let terrain =
|
||||
point_gen::HexTerrainMesh::generate(SIZE, |point| -> point_gen::TerrainVertex {
|
||||
use noise::NoiseFn;
|
||||
use rand::Rng;
|
||||
let noise = terrain_noise.get([point[0] as f64 / 5.0, point[1] as f64 / 5.0]) + 0.1;
|
||||
|
||||
let y = noise as f32 * 8.0;
|
||||
let y = noise as f32 * 8.0;
|
||||
|
||||
// Multiplies a colour by some random amount.
|
||||
fn mul_arr(mut arr: [u8; 4], by: f32) -> [u8; 4] {
|
||||
arr[0] = (arr[0] as f32 * by).min(255.0) as u8;
|
||||
arr[1] = (arr[1] as f32 * by).min(255.0) as u8;
|
||||
arr[2] = (arr[2] as f32 * by).min(255.0) as u8;
|
||||
arr
|
||||
}
|
||||
// Multiplies a colour by some random amount.
|
||||
fn mul_arr(mut arr: [u8; 4], by: f32) -> [u8; 4] {
|
||||
arr[0] = (arr[0] as f32 * by).min(255.0) as u8;
|
||||
arr[1] = (arr[1] as f32 * by).min(255.0) as u8;
|
||||
arr[2] = (arr[2] as f32 * by).min(255.0) as u8;
|
||||
arr
|
||||
}
|
||||
|
||||
// Under water
|
||||
const DARK_SAND: [u8; 4] = [235, 175, 71, 255];
|
||||
// Coast
|
||||
const SAND: [u8; 4] = [217, 191, 76, 255];
|
||||
// Normal
|
||||
const GRASS: [u8; 4] = [122, 170, 19, 255];
|
||||
// Mountain
|
||||
const SNOW: [u8; 4] = [175, 224, 237, 255];
|
||||
// Under water
|
||||
const DARK_SAND: [u8; 4] = [235, 175, 71, 255];
|
||||
// Coast
|
||||
const SAND: [u8; 4] = [217, 191, 76, 255];
|
||||
// Normal
|
||||
const GRASS: [u8; 4] = [122, 170, 19, 255];
|
||||
// Mountain
|
||||
const SNOW: [u8; 4] = [175, 224, 237, 255];
|
||||
|
||||
// Random colouration.
|
||||
let random = terrain_random.gen::<f32>() * 0.2 + 0.9;
|
||||
// Random colouration.
|
||||
let random = terrain_random.gen::<f32>() * 0.2 + 0.9;
|
||||
|
||||
// Choose colour.
|
||||
let colour = if y <= 0.0 {
|
||||
DARK_SAND
|
||||
} else if y <= 0.8 {
|
||||
SAND
|
||||
} else if y <= 3.0 {
|
||||
GRASS
|
||||
} else {
|
||||
SNOW
|
||||
};
|
||||
point_gen::TerrainVertex {
|
||||
position: Point3 { x: point[0], y, z: point[1] },
|
||||
colour: mul_arr(colour, random),
|
||||
}
|
||||
});
|
||||
// Choose colour.
|
||||
let colour = if y <= 0.0 {
|
||||
DARK_SAND
|
||||
} else if y <= 0.8 {
|
||||
SAND
|
||||
} else if y <= 3.0 {
|
||||
GRASS
|
||||
} else {
|
||||
SNOW
|
||||
};
|
||||
point_gen::TerrainVertex {
|
||||
position: Point3 {
|
||||
x: point[0],
|
||||
y,
|
||||
z: point[1],
|
||||
},
|
||||
colour: mul_arr(colour, random),
|
||||
}
|
||||
});
|
||||
|
||||
// Generate the buffer data.
|
||||
let terrain_vertices = terrain.make_buffer_data();
|
||||
@@ -323,92 +349,100 @@ impl framework::Example for Example {
|
||||
);
|
||||
|
||||
// Create the bind group layout. This is what our uniforms will look like.
|
||||
let water_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Water Bind Group Layout"),
|
||||
bindings: &[
|
||||
// Uniform variables such as projection/view.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
count: None,
|
||||
..Default::default()
|
||||
},
|
||||
// Reflection texture.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
..Default::default()
|
||||
},
|
||||
// Depth texture for terrain.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
..Default::default()
|
||||
},
|
||||
// Sampler to be able to sample the textures.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler { comparison: false },
|
||||
count: None,
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
});
|
||||
let water_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Water Bind Group Layout"),
|
||||
bindings: &[
|
||||
// Uniform variables such as projection/view.
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(mem::size_of::<
|
||||
WaterUniforms,
|
||||
>(
|
||||
)
|
||||
as _),
|
||||
},
|
||||
),
|
||||
// Reflection texture.
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
1,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
),
|
||||
// Depth texture for terrain.
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
2,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::SampledTexture {
|
||||
multisampled: false,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
},
|
||||
),
|
||||
// Sampler to be able to sample the textures.
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
3,
|
||||
wgpu::ShaderStage::FRAGMENT,
|
||||
wgpu::BindingType::Sampler { comparison: false },
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
let terrain_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Terrain Bind Group Layout"),
|
||||
bindings: &[
|
||||
// Regular uniform variables like view/projection.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
count: None,
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
});
|
||||
let terrain_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Terrain Bind Group Layout"),
|
||||
bindings: &[
|
||||
// Regular uniform variables like view/projection.
|
||||
wgpu::BindGroupLayoutEntry::new(
|
||||
0,
|
||||
wgpu::ShaderStage::VERTEX,
|
||||
wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: wgpu::NonZeroBufferAddress::new(mem::size_of::<
|
||||
TerrainUniforms,
|
||||
>(
|
||||
)
|
||||
as _),
|
||||
},
|
||||
),
|
||||
],
|
||||
});
|
||||
|
||||
// Create our pipeline layouts.
|
||||
let water_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&water_bind_group_layout],
|
||||
});
|
||||
let water_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&water_bind_group_layout],
|
||||
});
|
||||
|
||||
let terrain_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&terrain_bind_group_layout],
|
||||
});
|
||||
let terrain_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&terrain_bind_group_layout],
|
||||
});
|
||||
|
||||
let water_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Water Uniforms"),
|
||||
size: std::mem::size_of::<WaterUniforms>() as _,
|
||||
size: mem::size_of::<WaterUniforms>() as _,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let terrain_normal_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Normal Terrain Uniforms"),
|
||||
size: std::mem::size_of::<TerrainUniforms>() as _,
|
||||
size: mem::size_of::<TerrainUniforms>() as _,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let terrain_flipped_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Flipped Terrain Uniforms"),
|
||||
size: std::mem::size_of::<TerrainUniforms>() as _,
|
||||
size: mem::size_of::<TerrainUniforms>() as _,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
@@ -423,27 +457,23 @@ impl framework::Example for Example {
|
||||
&water_uniform_buf,
|
||||
&terrain_normal_uniform_buf,
|
||||
&terrain_flipped_uniform_buf,
|
||||
&water_bind_group_layout
|
||||
&water_bind_group_layout,
|
||||
);
|
||||
|
||||
let terrain_normal_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &terrain_bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(terrain_normal_uniform_buf.slice(..)),
|
||||
},
|
||||
],
|
||||
bindings: &[wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(terrain_normal_uniform_buf.slice(..)),
|
||||
}],
|
||||
label: Some("Terrain Normal Bind Group"),
|
||||
});
|
||||
let terrain_flipped_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &terrain_bind_group_layout,
|
||||
bindings: &[
|
||||
wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(terrain_flipped_uniform_buf.slice(..))
|
||||
}
|
||||
],
|
||||
bindings: &[wgpu::Binding {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(terrain_flipped_uniform_buf.slice(..)),
|
||||
}],
|
||||
label: Some("Terrain Flipped Bind Group"),
|
||||
});
|
||||
|
||||
@@ -452,16 +482,18 @@ impl framework::Example for Example {
|
||||
let water_fs_bytes = include_bytes!("water_shader.frag.spv");
|
||||
// Upload/compile them to GPU code.
|
||||
let water_vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&water_vs_bytes[..])).unwrap());
|
||||
.create_shader_module(&wgpu::read_spirv(io::Cursor::new(&water_vs_bytes[..])).unwrap());
|
||||
let water_fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&water_fs_bytes[..])).unwrap());
|
||||
.create_shader_module(&wgpu::read_spirv(io::Cursor::new(&water_fs_bytes[..])).unwrap());
|
||||
|
||||
let terrain_vs_bytes = include_bytes!("terrain_shader.vert.spv");
|
||||
let terrain_fs_bytes = include_bytes!("terrain_shader.frag.spv");
|
||||
let terrain_vs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&terrain_vs_bytes[..])).unwrap());
|
||||
let terrain_fs_module = device
|
||||
.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&terrain_fs_bytes[..])).unwrap());
|
||||
let terrain_vs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(io::Cursor::new(&terrain_vs_bytes[..])).unwrap(),
|
||||
);
|
||||
let terrain_fs_module = device.create_shader_module(
|
||||
&wgpu::read_spirv(io::Cursor::new(&terrain_fs_bytes[..])).unwrap(),
|
||||
);
|
||||
|
||||
// Create the render pipelines. These describe how the data will flow through the GPU, and what
|
||||
// constraints and modifiers it will have.
|
||||
@@ -531,13 +563,11 @@ impl framework::Example for Example {
|
||||
// because we duplicate all the data anyway. This is
|
||||
// necessary to achieve the low-poly effect.
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[
|
||||
wgpu::VertexBufferDescriptor {
|
||||
stride: water_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Short2, 1 => Char4],
|
||||
},
|
||||
],
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: water_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Short2, 1 => Char4],
|
||||
}],
|
||||
},
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
@@ -580,13 +610,11 @@ impl framework::Example for Example {
|
||||
}),
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[
|
||||
wgpu::VertexBufferDescriptor {
|
||||
stride: terrain_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float3, 1 => Float3, 2 => Uchar4Norm],
|
||||
},
|
||||
],
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: terrain_vertex_size as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &vertex_attr_array![0 => Float3, 1 => Float3, 2 => Uchar4Norm],
|
||||
}],
|
||||
},
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
@@ -652,7 +680,7 @@ impl framework::Example for Example {
|
||||
&self.water_uniform_buf,
|
||||
&self.terrain_normal_uniform_buf,
|
||||
&self.terrain_flipped_uniform_buf,
|
||||
&self.water_bind_group_layout
|
||||
&self.water_bind_group_layout,
|
||||
);
|
||||
self.water_bind_group = water_bind_group;
|
||||
|
||||
@@ -671,12 +699,17 @@ impl framework::Example for Example {
|
||||
|
||||
// Write the sin/cos values to the uniform buffer for the water.
|
||||
let (water_sin, water_cos) = ((self.current_frame as f32) / 600.0).sin_cos();
|
||||
queue.write_buffer(&self.water_uniform_buf, std::mem::size_of::<[f32; 16]>() as wgpu::BufferAddress * 2, bytemuck::cast_slice(&[water_sin, water_cos]));
|
||||
queue.write_buffer(
|
||||
&self.water_uniform_buf,
|
||||
mem::size_of::<[f32; 16]>() as wgpu::BufferAddress * 2,
|
||||
bytemuck::cast_slice(&[water_sin, water_cos]),
|
||||
);
|
||||
|
||||
// The encoder provides a way to turn our instructions here, into
|
||||
// a command buffer the GPU can understand.
|
||||
let mut encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Main Command Encoder") });
|
||||
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("Main Command Encoder"),
|
||||
});
|
||||
|
||||
// Only render valid frames. See resize method.
|
||||
if let Some(active) = self.active {
|
||||
@@ -690,20 +723,18 @@ impl framework::Example for Example {
|
||||
// First pass: render the reflection.
|
||||
{
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &self.reflect_view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &self.reflect_view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
],
|
||||
}],
|
||||
// We still need to use the depth buffer here
|
||||
// since the pipeline requires it.
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
@@ -727,20 +758,18 @@ impl framework::Example for Example {
|
||||
// depth values, so we must use StoreOp::Store.
|
||||
{
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Clear,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
],
|
||||
}],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &self.depth_buffer,
|
||||
depth_load_op: wgpu::LoadOp::Clear,
|
||||
@@ -762,20 +791,18 @@ impl framework::Example for Example {
|
||||
// to it, so it cannot be in the same render pass.
|
||||
{
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[
|
||||
wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Load,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
|
||||
attachment: &frame.view,
|
||||
resolve_target: None,
|
||||
load_op: wgpu::LoadOp::Load,
|
||||
store_op: wgpu::StoreOp::Store,
|
||||
clear_color: wgpu::Color {
|
||||
r: 161.0 / 255.0,
|
||||
g: 246.0 / 255.0,
|
||||
b: 255.0 / 255.0,
|
||||
a: 1.0,
|
||||
},
|
||||
],
|
||||
}],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &self.depth_buffer,
|
||||
depth_load_op: wgpu::LoadOp::Load,
|
||||
@@ -795,7 +822,6 @@ impl framework::Example for Example {
|
||||
rpass.draw(0..self.water_vertex_count as u32, 0..1);
|
||||
}
|
||||
|
||||
|
||||
encoder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//! This module covers generating points in a hexagonal fashion.
|
||||
//!
|
||||
|
||||
use cgmath::{InnerSpace, Point3, Vector3};
|
||||
use std::collections::HashMap;
|
||||
use cgmath::{Vector3, Point3, InnerSpace};
|
||||
|
||||
// The following constants are used in calculations.
|
||||
// A and B are multiplication factors for x and y.
|
||||
@@ -83,9 +83,16 @@ fn surrounding_hexagonal_points(x: isize, y: isize) -> [(isize, isize); 6] {
|
||||
]
|
||||
}
|
||||
|
||||
fn surrounding_point_values_iter<T>(hashmap: &HashMap<(isize, isize), T>, x: isize, y: isize, for_each: impl FnMut((&T, &T))) {
|
||||
fn surrounding_point_values_iter<T>(
|
||||
hashmap: &HashMap<(isize, isize), T>,
|
||||
x: isize,
|
||||
y: isize,
|
||||
for_each: impl FnMut((&T, &T)),
|
||||
) {
|
||||
let points = surrounding_hexagonal_points(x, y);
|
||||
let points = [points[0], points[1], points[2], points[3], points[4], points[5], points[0]];
|
||||
let points = [
|
||||
points[0], points[1], points[2], points[3], points[4], points[5], points[0],
|
||||
];
|
||||
points
|
||||
.windows(2)
|
||||
.map(|x| (hashmap.get(&x[0]), hashmap.get(&x[1])))
|
||||
@@ -160,9 +167,16 @@ impl HexTerrainMesh {
|
||||
}
|
||||
}
|
||||
fn half(p1: &TerrainVertex, p2: &TerrainVertex) -> Point3<f32> {
|
||||
Point3 { x: (p1.position.x + p2.position.x) / 2.0, y: (p1.position.y + p2.position.y) / 2.0, z: (p1.position.z + p2.position.z) / 2.0 }
|
||||
Point3 {
|
||||
x: (p1.position.x + p2.position.x) / 2.0,
|
||||
y: (p1.position.y + p2.position.y) / 2.0,
|
||||
z: (p1.position.z + p2.position.z) / 2.0,
|
||||
}
|
||||
}
|
||||
let mut push_triangle = |p1: &TerrainVertex, p2: &TerrainVertex, p: &TerrainVertex, c: [u8; 4]| {
|
||||
let mut push_triangle = |p1: &TerrainVertex,
|
||||
p2: &TerrainVertex,
|
||||
p: &TerrainVertex,
|
||||
c: [u8; 4]| {
|
||||
let m = middle(p1, p2, p);
|
||||
let ap = half(p1, p);
|
||||
let bp = half(p2, p);
|
||||
@@ -170,28 +184,27 @@ impl HexTerrainMesh {
|
||||
let n1 = calculate_normal(ap, m, p);
|
||||
let n2 = calculate_normal(m, bp, p);
|
||||
|
||||
vertices
|
||||
.extend(
|
||||
[ap, m, p, m, bp, p]
|
||||
.iter()
|
||||
.zip(std::iter::repeat::<[f32; 3]>(n1.into()).chain(std::iter::repeat::<[f32; 3]>(n2.into())))
|
||||
.zip(std::iter::repeat(c))
|
||||
.map(|((pos, normal), colour)| TerrainVertexAttributes {
|
||||
position: *pos.as_ref(),
|
||||
normal,
|
||||
colour,
|
||||
})
|
||||
);
|
||||
vertices.extend(
|
||||
[ap, m, p, m, bp, p]
|
||||
.iter()
|
||||
.zip(
|
||||
std::iter::repeat::<[f32; 3]>(n1.into())
|
||||
.chain(std::iter::repeat::<[f32; 3]>(n2.into())),
|
||||
)
|
||||
.zip(std::iter::repeat(c))
|
||||
.map(|((pos, normal), colour)| TerrainVertexAttributes {
|
||||
position: *pos.as_ref(),
|
||||
normal,
|
||||
colour,
|
||||
}),
|
||||
);
|
||||
};
|
||||
for i in -self.half_size..=self.half_size {
|
||||
for j in -self.half_size..=self.half_size {
|
||||
if let Some(p) = self.vertices.get(&(i, j)) {
|
||||
surrounding_point_values_iter(
|
||||
&self.vertices,
|
||||
i,
|
||||
j,
|
||||
|(a, b)| push_triangle(a, b, p, p.colour)
|
||||
);
|
||||
surrounding_point_values_iter(&self.vertices, i, j, |(a, b)| {
|
||||
push_triangle(a, b, p, p.colour)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,7 +259,7 @@ impl HexWaterMesh {
|
||||
(b[0] - a[0]) as i8,
|
||||
(b[1] - a[1]) as i8,
|
||||
(c[0] - a[0]) as i8,
|
||||
(c[1] - a[1]) as i8
|
||||
(c[1] - a[1]) as i8,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -259,7 +272,7 @@ impl HexWaterMesh {
|
||||
[a, b, c]
|
||||
.iter()
|
||||
.zip([bc, ca, ab].iter())
|
||||
.map(|(&position, &offsets)| WaterVertexAttributes { position, offsets })
|
||||
.map(|(&position, &offsets)| WaterVertexAttributes { position, offsets }),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -267,12 +280,9 @@ impl HexWaterMesh {
|
||||
for j in -self.half_size..=self.half_size {
|
||||
if (i - j) % 3 == 0 {
|
||||
if let Some(&p) = self.vertices.get(&(i, j)) {
|
||||
surrounding_point_values_iter(
|
||||
&self.vertices,
|
||||
i,
|
||||
j,
|
||||
|(a, b)| push_triangle(*a, *b, p)
|
||||
);
|
||||
surrounding_point_values_iter(&self.vertices, i, j, |(a, b)| {
|
||||
push_triangle(*a, *b, p)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,14 +806,20 @@ impl crate::Context for Context {
|
||||
);
|
||||
|
||||
match bind.ty {
|
||||
BindingType::UniformBuffer { dynamic }
|
||||
BindingType::UniformBuffer { dynamic, .. }
|
||||
| BindingType::StorageBuffer { dynamic, .. } => {
|
||||
mapped_entry.has_dynamic_offset(dynamic);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let BindingType::SampledTexture { multisampled, .. } = bind.ty {
|
||||
if let BindingType::SampledTexture {
|
||||
component_type,
|
||||
multisampled,
|
||||
..
|
||||
} = bind.ty
|
||||
{
|
||||
mapped_entry.texture_component_type(map_texture_component_type(component_type));
|
||||
mapped_entry.multisampled(multisampled);
|
||||
}
|
||||
|
||||
@@ -829,15 +835,6 @@ impl crate::Context for Context {
|
||||
mapped_entry.storage_texture_format(map_texture_format(format));
|
||||
}
|
||||
|
||||
match bind.ty {
|
||||
BindingType::SampledTexture { component_type, .. }
|
||||
| BindingType::StorageTexture { component_type, .. } => {
|
||||
mapped_entry
|
||||
.texture_component_type(map_texture_component_type(component_type));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
mapped_entry
|
||||
})
|
||||
.collect::<js_sys::Array>();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! A cross-platform graphics and compute library based on WebGPU.
|
||||
|
||||
mod backend;
|
||||
|
||||
mod util;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
@@ -19,20 +19,21 @@ use parking_lot::Mutex;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use wgc::instance::{AdapterInfo, DeviceType};
|
||||
pub use wgt::{
|
||||
read_spirv, AddressMode, Backend, BackendBit, BindGroupLayoutDescriptor, BindGroupLayoutEntry,
|
||||
BindingType, BlendDescriptor, BlendFactor, BlendOperation, BufferAddress, BufferSize,
|
||||
BufferUsage, Capabilities, Color, ColorStateDescriptor, ColorWrite, CommandBufferDescriptor,
|
||||
AddressMode, Backend, BackendBit, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType,
|
||||
BlendDescriptor, BlendFactor, BlendOperation, BufferAddress, BufferSize, BufferUsage,
|
||||
Capabilities, Color, ColorStateDescriptor, ColorWrite, CommandBufferDescriptor,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset,
|
||||
Extensions, Extent3d, FilterMode, FrontFace, IndexFormat, InputStepMode, Limits, LoadOp,
|
||||
Origin3d, PowerPreference, PresentMode, PrimitiveTopology, RasterizationStateDescriptor,
|
||||
RenderBundleEncoderDescriptor, ShaderLocation, ShaderStage, StencilOperation,
|
||||
StencilStateFaceDescriptor, StoreOp, SwapChainDescriptor, SwapChainStatus, TextureAspect,
|
||||
TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat, TextureUsage,
|
||||
TextureViewDimension, UnsafeExtensions, VertexAttributeDescriptor, VertexFormat,
|
||||
NonZeroBufferAddress, Origin3d, PowerPreference, PresentMode, PrimitiveTopology,
|
||||
RasterizationStateDescriptor, RenderBundleEncoderDescriptor, ShaderLocation, ShaderStage,
|
||||
StencilOperation, StencilStateFaceDescriptor, StoreOp, SwapChainDescriptor, SwapChainStatus,
|
||||
TextureAspect, TextureComponentType, TextureDataLayout, TextureDimension, TextureFormat,
|
||||
TextureUsage, TextureViewDimension, UnsafeExtensions, VertexAttributeDescriptor, VertexFormat,
|
||||
BIND_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
|
||||
};
|
||||
|
||||
use backend::Context as C;
|
||||
pub use util::read_spirv;
|
||||
|
||||
trait ComputePassInner<Ctx: Context> {
|
||||
fn set_pipeline(&mut self, pipeline: &Ctx::ComputePipelineId);
|
||||
|
||||
41
wgpu/src/util/mod.rs
Normal file
41
wgpu/src/util/mod.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use std::{io, slice};
|
||||
|
||||
// TODO: This is copy/pasted from gfx-hal, so we need to find a new place to put
|
||||
// this function
|
||||
pub fn read_spirv<R: io::Read + io::Seek>(mut x: R) -> io::Result<Vec<u32>> {
|
||||
let size = x.seek(io::SeekFrom::End(0))?;
|
||||
if size % 4 != 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"input length not divisible by 4",
|
||||
));
|
||||
}
|
||||
if size > usize::max_value() as u64 {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
|
||||
}
|
||||
let words = (size / 4) as usize;
|
||||
let mut result = Vec::<u32>::with_capacity(words);
|
||||
x.seek(io::SeekFrom::Start(0))?;
|
||||
unsafe {
|
||||
// Writing all bytes through a pointer with less strict alignment when our type has no
|
||||
// invalid bitpatterns is safe.
|
||||
x.read_exact(slice::from_raw_parts_mut(
|
||||
result.as_mut_ptr() as *mut u8,
|
||||
words * 4,
|
||||
))?;
|
||||
result.set_len(words);
|
||||
}
|
||||
const MAGIC_NUMBER: u32 = 0x0723_0203;
|
||||
if !result.is_empty() && result[0] == MAGIC_NUMBER.swap_bytes() {
|
||||
for word in &mut result {
|
||||
*word = word.swap_bytes();
|
||||
}
|
||||
}
|
||||
if result.is_empty() || result[0] != MAGIC_NUMBER {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"input missing SPIR-V magic number",
|
||||
));
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
Reference in New Issue
Block a user