Galactica/crates/render/src/globaluniform/globaluniform.rs

172 lines
4.2 KiB
Rust

use wgpu;
use super::{AtlasContent, DataContent, SpriteContent};
pub struct GlobalUniform {
pub data_buffer: wgpu::Buffer,
pub atlas_buffer: wgpu::Buffer,
pub sprite_buffer: wgpu::Buffer,
pub bind_group: wgpu::BindGroup,
pub bind_group_layout: wgpu::BindGroupLayout,
pub content: DataContent,
}
impl GlobalUniform {
pub fn shader_header(&self, group: u32) -> String {
let mut out = String::new();
out.push_str(&format!("@group({group}) @binding(0)\n"));
out.push_str(
r#"
var<uniform> global: GlobalUniform;
struct GlobalUniform {
camera_position: vec2<f32>,
camera_zoom: vec2<f32>,
camera_zoom_limits: vec2<f32>,
window_size: vec2<f32>,
window_aspect: vec2<f32>,
starfield_sprite: vec2<u32>,
starfield_tile_size: vec2<f32>,
starfield_size_limits: vec2<f32>,
current_time: vec2<f32>,
};
"#,
);
out.push_str("\n");
out.push_str(&format!("@group({group}) @binding(1)\n"));
out.push_str(
r#"
var<uniform> atlas: AtlasUniform;
struct ImageLocation {
xpos: f32,
ypos: f32,
width: f32,
height: f32,
};
struct AtlasUniform {
data: array<ImageLocation, 108>,
};
"#,
);
out.push_str("\n");
// TODO: document
// wgpu uniforms require constant item sizes.
// if you get an error like the following,check!
// `Buffer is bound with size 3456 where the shader expects 5184 in group[1] compact index 2`
// More notes are in datacontent
out.push_str(&format!("@group({group}) @binding(2)\n"));
out.push_str(
r#"
var<uniform> sprites: SpriteUniform;
struct SpriteData {
frame_count: u32,
repeatmode: u32,
aspect: f32,
fps: f32,
first_frame: u32,
padding_a: f32,
padding_b: f32,
padding_c: f32,
};
struct SpriteUniform {
data: array<SpriteData, 108>,
};
"#,
);
out.push_str("\n");
return out;
}
pub fn new(device: &wgpu::Device) -> Self {
let data_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("global uniform data buffer"),
size: DataContent::SIZE,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let atlas_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("global uniform atlas buffer"),
size: AtlasContent::SIZE,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let sprite_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("global uniform sprite buffer"),
size: SpriteContent::SIZE,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
],
label: Some("global uniform bind group layout"),
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: data_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: atlas_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: sprite_buffer.as_entire_binding(),
},
],
label: Some("global uniform bind group"),
});
return Self {
data_buffer,
atlas_buffer,
sprite_buffer,
bind_group,
bind_group_layout,
content: DataContent::default(),
};
}
}