Galactica/crates/render/src/vertexbuffer/vertexbuffer.rs

98 lines
2.5 KiB
Rust

use wgpu::{self, util::DeviceExt};
use super::BufferObject;
pub struct VertexBuffer {
/// Vertices to draw.
///
/// This can be set to None if each instance
/// only needs one vertex. Note that the shader
/// must be prepared for this!
vertices: Option<wgpu::Buffer>,
/// Vertex indices. This will be None if we're
/// drawing vertices directly, without indices.
indices: Option<wgpu::Buffer>,
pub instances: wgpu::Buffer,
pub layout: Box<[wgpu::VertexBufferLayout<'static>]>,
}
impl VertexBuffer {
pub fn new<VertexType, InstanceType>(
label: &str,
device: &wgpu::Device,
vertices: Option<&[VertexType]>,
indices: Option<&[u16]>,
length: u64,
) -> Self
where
VertexType: BufferObject,
InstanceType: BufferObject,
{
let vertices = if let Some(vertices) = vertices {
Some(
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("[{}] vertex buffer", label)),
contents: bytemuck::cast_slice(vertices),
usage: wgpu::BufferUsages::VERTEX,
}),
)
} else {
None
};
let indices = if let Some(indices) = indices {
if vertices.is_none() {
unreachable!("Bad code! You cannot draw indexed vertices if vertices is None!")
}
Some(
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&format!("[{}] index buffer", label)),
contents: bytemuck::cast_slice(indices),
usage: wgpu::BufferUsages::INDEX,
}),
)
} else {
None
};
let instances = device.create_buffer(&wgpu::BufferDescriptor {
label: Some(&format!("[{}] instance buffer", label)),
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
size: InstanceType::SIZE * length,
mapped_at_creation: false,
});
let mut layout = Vec::new();
if vertices.is_some() {
layout.push(VertexType::layout());
}
layout.push(InstanceType::layout());
Self {
vertices,
indices,
instances,
layout: layout.into(),
}
}
/// Set the buffers defined here as buffers in a RenderPass.
pub fn set_in_pass<'a, 'b: 'a>(&'b self, render_pass: &'a mut wgpu::RenderPass<'b>) {
// TODO: why do these lifetimes work?
let mut v_slot = 0u32;
if let Some(vertices) = &self.vertices {
render_pass.set_vertex_buffer(v_slot, vertices.slice(..));
v_slot += 1;
}
render_pass.set_vertex_buffer(v_slot, self.instances.slice(..));
//v_slot += 1;
if let Some(indices) = &self.indices {
render_pass.set_index_buffer(indices.slice(..), wgpu::IndexFormat::Uint16);
}
}
}