Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to wgpu 0.9 #179

Merged
merged 7 commits into from
Jun 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ include = [
]

[dependencies]
bytemuck = "1.7"
pollster = "0.2"
raw-window-handle = "0.3"
thiserror = "1.0"
ultraviolet = "0.8"
wgpu = "0.8.1"
wgpu = "0.9"

[dev-dependencies]
pixels-mocks = { path = "internals/pixels-mocks" }
Expand Down
2 changes: 1 addition & 1 deletion examples/conway/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn create_window(
let window = winit::window::WindowBuilder::new()
.with_visible(false)
.with_title(title)
.build(&event_loop)
.build(event_loop)
.unwrap();
let hidpi_factor = window.scale_factor();

Expand Down
1 change: 1 addition & 0 deletions examples/custom-shader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ optimize = ["log/release_max_level_warn"]
default = ["optimize"]

[dependencies]
bytemuck = "1.7"
env_logger = "0.8"
log = "0.4"
pixels = { path = "../.." }
Expand Down
39 changes: 8 additions & 31 deletions examples/custom-shader/shaders/noise.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,14 @@ struct VertexOutput {
[[builtin(position)]] position: vec4<f32>;
};

let positions: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
// Upper left triangle
vec2<f32>(-1.0, -1.0),
vec2<f32>(1.0, -1.0),
vec2<f32>(-1.0, 1.0),

// Lower right triangle
vec2<f32>(-1.0, 1.0),
vec2<f32>(1.0, -1.0),
vec2<f32>(1.0, 1.0),
);

let uv: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
// Upper left triangle
vec2<f32>(0.0, 0.0),
vec2<f32>(1.0, 0.0),
vec2<f32>(0.0, 1.0),

// Lower right triangle
vec2<f32>(0.0, 1.0),
vec2<f32>(1.0, 0.0),
vec2<f32>(1.0, 1.0),
);

[[stage(vertex)]]
fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> VertexOutput {
fn vs_main(
[[location(0)]] position: vec2<f32>,
[[location(1)]] tex_coord: vec2<f32>,
) -> VertexOutput {
var out: VertexOutput;
out.tex_coord = uv[vertex_index];
out.position = vec4<f32>(positions[vertex_index], 0.0, 1.0);
out.tex_coord = tex_coord;
out.position = vec4<f32>(position, 0.0, 1.0);
return out;
}

Expand Down Expand Up @@ -64,10 +43,8 @@ fn random_vec2(st: vec2<f32>) -> f32 {

[[stage(fragment)]]
fn fs_main([[location(0)]] tex_coord: vec2<f32>) -> [[location(0)]] vec4<f32> {
let sampled_color: vec4<f32> = textureSample(r_tex_color, r_tex_sampler, tex_coord);
let noise_color: vec3<f32> = vec3<f32>(random_vec2(
tex_coord.xy * vec2<f32>(r_locals.time % tau + bias)
));
let sampled_color = textureSample(r_tex_color, r_tex_sampler, tex_coord);
let noise_color = vec3<f32>(random_vec2(tex_coord.xy * vec2<f32>(r_locals.time % tau + bias)));

return vec4<f32>(sampled_color.rgb * noise_color, sampled_color.a);
}
37 changes: 7 additions & 30 deletions examples/custom-shader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use crate::renderers::NoiseRenderer;
use log::error;
use pixels::{wgpu, Error, Pixels, SurfaceTexture};
use pixels::{Error, Pixels, SurfaceTexture};
use winit::dpi::LogicalSize;
use winit::event::{Event, VirtualKeyCode};
use winit::event_loop::{ControlFlow, EventLoop};
Expand Down Expand Up @@ -44,22 +44,22 @@ fn main() -> Result<(), Error> {
Pixels::new(WIDTH, HEIGHT, surface_texture)?
};
let mut world = World::new();

let mut time = 0.0;
let (scaled_texture, noise_renderer) = create_noise_renderer(&pixels);
let mut noise_renderer = NoiseRenderer::new(pixels.device(), WIDTH, HEIGHT);

event_loop.run(move |event, _, control_flow| {
// Draw the current frame
if let Event::RedrawRequested(_) = event {
world.draw(pixels.get_frame());

let render_result = pixels.render_with(|encoder, render_target, context| {
context.scaling_renderer.render(encoder, &scaled_texture);
let noise_texture = noise_renderer.get_texture_view();
context.scaling_renderer.render(encoder, noise_texture);

noise_renderer.update(&context.queue, time);
time += 0.01;

noise_renderer.render(encoder, render_target);
noise_renderer.render(encoder, render_target, context.scaling_renderer.clip_rect());
});

if render_result
Expand All @@ -82,6 +82,7 @@ fn main() -> Result<(), Error> {
// Resize the window
if let Some(size) = input.window_resized() {
pixels.resize_surface(size.width, size.height);
noise_renderer.resize(pixels.device(), size.width, size.height);
}

// Update internal state and request a redraw
Expand Down Expand Up @@ -117,7 +118,7 @@ impl World {

/// Draw the `World` state to the frame buffer.
///
/// Assumes the default texture format: [`wgpu::TextureFormat::Rgba8UnormSrgb`]
/// Assumes the default texture format: [`pixels::wgpu::TextureFormat::Rgba8UnormSrgb`]
fn draw(&self, frame: &mut [u8]) {
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
let x = (i % WIDTH as usize) as i16;
Expand All @@ -138,27 +139,3 @@ impl World {
}
}
}

fn create_noise_renderer(pixels: &Pixels) -> (wgpu::TextureView, NoiseRenderer) {
let device = &pixels.device();

let texture_descriptor = wgpu::TextureDescriptor {
label: None,
size: pixels::wgpu::Extent3d {
width: WIDTH,
height: HEIGHT,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
};
let scaled_texture = device
.create_texture(&texture_descriptor)
.create_view(&wgpu::TextureViewDescriptor::default());
let noise_renderer = NoiseRenderer::new(device, &scaled_texture);

(scaled_texture, noise_renderer)
}
154 changes: 123 additions & 31 deletions examples/custom-shader/src/renderers.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
use pixels::wgpu::{self, util::DeviceExt};
use std::borrow::Cow;

pub(crate) struct NoiseRenderer {
texture_view: wgpu::TextureView,
sampler: wgpu::Sampler,
bind_group_layout: wgpu::BindGroupLayout,
bind_group: wgpu::BindGroup,
render_pipeline: wgpu::RenderPipeline,
time_buffer: wgpu::Buffer,
vertex_buffer: wgpu::Buffer,
}

impl NoiseRenderer {
pub(crate) fn new(device: &wgpu::Device, texture_view: &wgpu::TextureView) -> Self {
let shader = wgpu::ShaderModuleDescriptor {
label: Some("custom_noise_shader"),
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("../shaders/noise.wgsl"))),
flags: wgpu::ShaderFlags::VALIDATION,
};
pub(crate) fn new(device: &wgpu::Device, width: u32, height: u32) -> Self {
let shader = wgpu::include_wgsl!("../shaders/noise.wgsl");
let module = device.create_shader_module(&shader);

// Create a texture view that will be used as input
// This will be used as the render target for the default scaling renderer
let texture_view = create_texture_view(device, width, height);

// Create a texture sampler with nearest neighbor
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("NoiseRenderer sampler"),
Expand All @@ -32,6 +35,37 @@ impl NoiseRenderer {
border_color: None,
});

// Create vertex buffer; array-of-array of position and texture coordinates
let vertex_data: [[[f32; 2]; 2]; 3] = [
// One full-screen triangle
// See: https://github.com/parasyte/pixels/issues/180
[[-1.0, -1.0], [0.0, 0.0]],
[[3.0, -1.0], [2.0, 0.0]],
[[-1.0, 3.0], [0.0, 2.0]],
];
let vertex_data_slice = bytemuck::cast_slice(&vertex_data);
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("NoiseRenderer vertex buffer"),
contents: vertex_data_slice,
usage: wgpu::BufferUsage::VERTEX,
});
let vertex_buffer_layout = wgpu::VertexBufferLayout {
array_stride: (vertex_data_slice.len() / vertex_data.len()) as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &[
wgpu::VertexAttribute {
format: wgpu::VertexFormat::Float32x2,
offset: 0,
shader_location: 0,
},
wgpu::VertexAttribute {
format: wgpu::VertexFormat::Float32x2,
offset: 4 * 2,
shader_location: 1,
},
],
};

// Create uniform buffer
let time_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("NoiseRenderer u_Time"),
Expand Down Expand Up @@ -74,28 +108,13 @@ impl NoiseRenderer {
},
],
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(texture_view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&sampler),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &time_buffer,
offset: 0,
size: None,
}),
},
],
});
let bind_group = create_bind_group(
device,
&bind_group_layout,
&texture_view,
&sampler,
&time_buffer,
);

// Create pipeline
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
Expand All @@ -109,7 +128,7 @@ impl NoiseRenderer {
vertex: wgpu::VertexState {
module: &module,
entry_point: "vs_main",
buffers: &[],
buffers: &[vertex_buffer_layout],
},
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
Expand All @@ -129,12 +148,31 @@ impl NoiseRenderer {
});

Self {
texture_view,
sampler,
bind_group_layout,
bind_group,
render_pipeline,
time_buffer,
vertex_buffer,
}
}

pub(crate) fn get_texture_view(&self) -> &wgpu::TextureView {
&self.texture_view
}

pub(crate) fn resize(&mut self, device: &wgpu::Device, width: u32, height: u32) {
self.texture_view = create_texture_view(device, width, height);
self.bind_group = create_bind_group(
device,
&self.bind_group_layout,
&self.texture_view,
&self.sampler,
&self.time_buffer,
);
}

pub(crate) fn update(&self, queue: &wgpu::Queue, time: f32) {
queue.write_buffer(&self.time_buffer, 0, &time.to_ne_bytes());
}
Expand All @@ -143,6 +181,7 @@ impl NoiseRenderer {
&self,
encoder: &mut wgpu::CommandEncoder,
render_target: &wgpu::TextureView,
clip_rect: (u32, u32, u32, u32),
) {
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("NoiseRenderer render pass"),
Expand All @@ -158,6 +197,59 @@ impl NoiseRenderer {
});
rpass.set_pipeline(&self.render_pipeline);
rpass.set_bind_group(0, &self.bind_group, &[]);
rpass.draw(0..6, 0..1);
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
rpass.set_scissor_rect(clip_rect.0, clip_rect.1, clip_rect.2, clip_rect.3);
rpass.draw(0..3, 0..1);
}
}

fn create_texture_view(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
let texture_descriptor = wgpu::TextureDescriptor {
label: None,
size: pixels::wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
};

device
.create_texture(&texture_descriptor)
.create_view(&wgpu::TextureViewDescriptor::default())
}

fn create_bind_group(
device: &wgpu::Device,
bind_group_layout: &wgpu::BindGroupLayout,
texture_view: &wgpu::TextureView,
sampler: &wgpu::Sampler,
time_buffer: &wgpu::Buffer,
) -> pixels::wgpu::BindGroup {
device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(texture_view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(sampler),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: time_buffer,
offset: 0,
size: None,
}),
},
],
})
}
Loading