Merge Pixels::update() with Pixels::render()

- Adds `PixelsBuilder::texture_format()` to configure the format for the pixel buffer
This commit is contained in:
Jay Oster 2019-10-03 23:16:23 -07:00
parent 7a858089bf
commit 64cd487c37
2 changed files with 87 additions and 17 deletions

View file

@ -58,7 +58,7 @@ fn main() -> Result<(), Error> {
let surface_texture = SurfaceTexture::new(width, height, &surface); let surface_texture = SurfaceTexture::new(width, height, &surface);
let mut fb = Pixels::new(320, 240, surface_texture)?; let mut fb = Pixels::new(320, 240, surface_texture)?;
fb.update(&scale_pixel_ferris(320, 240)); let ferris = scale_pixel_ferris(320, 240);
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, _, control_flow| match event {
event::Event::WindowEvent { event, .. } => match event { event::Event::WindowEvent { event, .. } => match event {
@ -72,7 +72,7 @@ fn main() -> Result<(), Error> {
.. ..
} }
| event::WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, | event::WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
event::WindowEvent::RedrawRequested => fb.render(), event::WindowEvent::RedrawRequested => fb.render(&ferris),
_ => (), _ => (),
}, },
event::Event::EventsCleared => window.request_redraw(), event::Event::EventsCleared => window.request_redraw(),

View file

@ -39,6 +39,7 @@ pub struct Pixels {
swap_chain: wgpu::SwapChain, swap_chain: wgpu::SwapChain,
texture_extent: wgpu::Extent3d, texture_extent: wgpu::Extent3d,
texture: wgpu::Texture, texture: wgpu::Texture,
texture_format_size: u32,
} }
/// A builder to help create customized pixel buffers. /// A builder to help create customized pixel buffers.
@ -50,6 +51,7 @@ pub struct PixelsBuilder<'a> {
height: u32, height: u32,
pixel_aspect_ratio: f64, pixel_aspect_ratio: f64,
surface_texture: SurfaceTexture<'a>, surface_texture: SurfaceTexture<'a>,
texture_format: wgpu::TextureFormat,
} }
/// Renderer implements RenderPass. /// Renderer implements RenderPass.
@ -137,12 +139,20 @@ impl Pixels {
// TODO: Support resize // TODO: Support resize
/// Update the pixel buffer with the `texels` byte slice. /// Draw this pixel buffer to the configured [`SurfaceTexture`].
pub fn update(&mut self, texels: &[u8]) { ///
/// # Arguments
///
/// * `texels` - Byte slice of texture pixels (AKA texels) to draw. The texture format can be
/// configured with `PixelsBuilder`.
pub fn render(&mut self, texels: &[u8]) {
// TODO: Center frame buffer in surface
let frame = self.swap_chain.get_next_texture();
let mut encoder = self let mut encoder = self
.device .device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); .create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
// Update the pixel buffer texture view
let buffer = self let buffer = self
.device .device
.create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC) .create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC)
@ -151,7 +161,7 @@ impl Pixels {
wgpu::BufferCopyView { wgpu::BufferCopyView {
buffer: &buffer, buffer: &buffer,
offset: 0, offset: 0,
row_pitch: 4 * self.width, row_pitch: self.width * self.texture_format_size,
image_height: self.height, image_height: self.height,
}, },
wgpu::TextureCopyView { wgpu::TextureCopyView {
@ -167,17 +177,6 @@ impl Pixels {
self.texture_extent, self.texture_extent,
); );
self.queue.submit(&[encoder.finish()]);
}
/// Draw this pixel buffer to the configured [`SurfaceTexture`].
pub fn render(&mut self) {
// TODO: Center frame buffer in surface
let frame = self.swap_chain.get_next_texture();
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
// TODO: Run all render passes in a loop // TODO: Run all render passes in a loop
self.renderer.render_pass(&mut encoder, &frame.view); self.renderer.render_pass(&mut encoder, &frame.view);
@ -236,6 +235,7 @@ impl<'a> PixelsBuilder<'a> {
height, height,
pixel_aspect_ratio: 1.0, pixel_aspect_ratio: 1.0,
surface_texture, surface_texture,
texture_format: wgpu::TextureFormat::Rgba8UnormSrgb,
} }
} }
@ -268,6 +268,16 @@ impl<'a> PixelsBuilder<'a> {
self self
} }
/// Set the texture format.
///
/// The default value is [`wgpu::TextureFormat::Rgba8UnormSrgb`], which is 4 unsigned bytes in
/// `RGBA` order using the SRGB color space. This is typically what you want when you are
/// working with color values from popular image editing tools or web apps.
pub fn texture_format(mut self, texture_format: wgpu::TextureFormat) -> PixelsBuilder<'a> {
self.texture_format = texture_format;
self
}
/// Create a pixel buffer from the options builder. /// Create a pixel buffer from the options builder.
/// ///
/// # Errors /// # Errors
@ -299,10 +309,11 @@ impl<'a> PixelsBuilder<'a> {
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb, format: self.texture_format,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST,
}); });
let texture_view = texture.create_default_view(); let texture_view = texture.create_default_view();
let texture_format_size = get_texture_format_size(self.texture_format);
// Create a texture sampler with nearest neighbor // Create a texture sampler with nearest neighbor
let sampler = device.create_sampler(&wgpu::SamplerDescriptor { let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
@ -412,6 +423,7 @@ impl<'a> PixelsBuilder<'a> {
swap_chain, swap_chain,
texture_extent, texture_extent,
texture, texture,
texture_format_size,
}) })
} }
} }
@ -429,3 +441,61 @@ impl StdError for Error {
} }
} }
} }
fn get_texture_format_size(texture_format: wgpu::TextureFormat) -> u32 {
match texture_format {
// 8-bit formats
wgpu::TextureFormat::R8Unorm
| wgpu::TextureFormat::R8Snorm
| wgpu::TextureFormat::R8Uint
| wgpu::TextureFormat::R8Sint => 1,
// 16-bit formats
wgpu::TextureFormat::R16Unorm
| wgpu::TextureFormat::R16Snorm
| wgpu::TextureFormat::R16Uint
| wgpu::TextureFormat::R16Sint
| wgpu::TextureFormat::R16Float
| wgpu::TextureFormat::Rg8Unorm
| wgpu::TextureFormat::Rg8Snorm
| wgpu::TextureFormat::Rg8Uint
| wgpu::TextureFormat::Rg8Sint => 2,
// 32-bit formats
wgpu::TextureFormat::R32Uint
| wgpu::TextureFormat::R32Sint
| wgpu::TextureFormat::R32Float
| wgpu::TextureFormat::Rg16Unorm
| wgpu::TextureFormat::Rg16Snorm
| wgpu::TextureFormat::Rg16Uint
| wgpu::TextureFormat::Rg16Sint
| wgpu::TextureFormat::Rg16Float
| wgpu::TextureFormat::Rgba8Unorm
| wgpu::TextureFormat::Rgba8UnormSrgb
| wgpu::TextureFormat::Rgba8Snorm
| wgpu::TextureFormat::Rgba8Uint
| wgpu::TextureFormat::Rgba8Sint
| wgpu::TextureFormat::Bgra8Unorm
| wgpu::TextureFormat::Bgra8UnormSrgb
| wgpu::TextureFormat::Rgb10a2Unorm
| wgpu::TextureFormat::Rg11b10Float
| wgpu::TextureFormat::Depth32Float
| wgpu::TextureFormat::Depth24Plus
| wgpu::TextureFormat::Depth24PlusStencil8 => 4,
// 64-bit formats
wgpu::TextureFormat::Rg32Uint
| wgpu::TextureFormat::Rg32Sint
| wgpu::TextureFormat::Rg32Float
| wgpu::TextureFormat::Rgba16Unorm
| wgpu::TextureFormat::Rgba16Snorm
| wgpu::TextureFormat::Rgba16Uint
| wgpu::TextureFormat::Rgba16Sint
| wgpu::TextureFormat::Rgba16Float => 8,
// 128-bit formats
wgpu::TextureFormat::Rgba32Uint
| wgpu::TextureFormat::Rgba32Sint
| wgpu::TextureFormat::Rgba32Float => 16,
}
}