Move shader structs

This commit is contained in:
Maximilian Ammann 2022-01-13 18:54:52 +01:00
parent d1602c35d0
commit ab6dc5892f
12 changed files with 183 additions and 183 deletions

View File

@ -2,8 +2,6 @@
use std::fmt;
use crate::render::shader_ffi::Vec3f32;
/// Every tile has tile coordinates. These tile coordinates are also called
/// [Slippy map tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames).
///
@ -133,22 +131,16 @@ impl AlignedWorldTileCoords {
}
}
#[derive(Clone, Copy, Debug)]
pub struct WorldCoords {
pub x: f32,
pub y: f32,
pub z: f32,
}
/// Actual coordinates within the 3d world.
///
/// # Coordinate System Origin
///
/// The origin of the coordinate system is in the upper-left corner.
impl WorldCoords {
pub fn into_shader_coords(self) -> Vec3f32 {
[self.x, self.y, self.z]
}
#[derive(Clone, Copy, Debug)]
pub struct WorldCoords {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl fmt::Display for WorldCoords {

View File

@ -9,14 +9,14 @@ use vector_tile::parse_tile_bytes;
use crate::io::web_tile_fetcher::WebTileFetcher;
use crate::io::TileFetcher;
use crate::render::shader_ffi::GpuVertexUniform;
use crate::render::ShaderVertex;
use crate::tesselation::{IndexDataType, OverAlignedVertexBuffer, Tesselated};
#[derive(Clone)]
pub struct TesselatedTile {
pub id: u32,
pub coords: TileCoords,
pub over_aligned: OverAlignedVertexBuffer<GpuVertexUniform, IndexDataType>,
pub over_aligned: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
}
#[derive(Clone)]

View File

@ -1,8 +1,7 @@
use crate::render::shaders::ShaderCamera;
use cgmath::prelude::*;
use cgmath::Matrix4;
use crate::render::shader_ffi::CameraUniform;
#[rustfmt::skip]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f64> = cgmath::Matrix4::new(
1.0, 0.0, 0.0, 0.0,
@ -56,9 +55,9 @@ impl Camera {
FLIP_Y * perspective.calc_matrix() * self.calc_matrix()
}
pub fn create_camera_uniform(&self, perspective: &Perspective) -> CameraUniform {
pub fn create_camera_uniform(&self, perspective: &Perspective) -> ShaderCamera {
let view_proj = self.calc_view_proj(perspective);
CameraUniform::new(
ShaderCamera::new(
view_proj.cast::<f32>().unwrap().into(),
self.position.to_homogeneous().cast::<f32>().unwrap().into(),
)

View File

@ -1,11 +1,13 @@
mod buffer_pool;
mod options;
mod piplines;
mod shaders;
mod texture;
mod tile_mask_pattern;
pub mod camera;
pub mod options;
pub mod render_state;
pub mod shader_ffi;
// These are created during tesselation and must be public
pub use shaders::ShaderVertex;

View File

@ -9,13 +9,14 @@ use winit::window::Window;
use crate::io::worker_loop::WorkerLoop;
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
use crate::render::buffer_pool::{BackingBufferDescriptor, BufferPool};
use crate::render::camera;
use crate::render::tile_mask_pattern::TileMaskPattern;
use crate::render::{camera, shaders};
use crate::tesselation::IndexDataType;
use crate::util::FPSMeter;
use super::piplines::*;
use super::shader_ffi::*;
use super::shaders;
use super::shaders::*;
use super::texture::Texture;
pub struct SceneParams {
@ -60,7 +61,7 @@ pub struct RenderState {
tiles_uniform_buffer: wgpu::Buffer,
globals_uniform_buffer: wgpu::Buffer,
buffer_pool: BufferPool<Queue, Buffer, GpuVertexUniform, IndexDataType>,
buffer_pool: BufferPool<Queue, Buffer, ShaderVertex, IndexDataType>,
tile_mask_pattern: TileMaskPattern,
tile_mask_instances_buffer: wgpu::Buffer,
@ -150,7 +151,7 @@ impl RenderState {
});
let tile_masks_uniform_buffer_size =
std::mem::size_of::<MaskInstanceUniform>() as u64 * TILE_MASK_INSTANCE_COUNT;
std::mem::size_of::<ShaderTileMaskInstance>() as u64 * TILE_MASK_INSTANCE_COUNT;
let tile_mask_instances = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
@ -159,12 +160,11 @@ impl RenderState {
mapped_at_creation: false,
});
let globals_buffer_byte_size = cmp::max(
MIN_BUFFER_SIZE,
std::mem::size_of::<GlobalsUniform>() as u64,
);
let globals_buffer_byte_size =
cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);
let tiles_uniform_buffer_size = std::mem::size_of::<TileUniform>() as u64 * TILE_META_COUNT;
let tiles_uniform_buffer_size =
std::mem::size_of::<ShaderTileMetadata>() as u64 * TILE_META_COUNT;
let tiles_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Tiles ubo"),
size: tiles_uniform_buffer_size,
@ -360,10 +360,10 @@ impl RenderState {
self.queue.write_buffer(
&self.tiles_uniform_buffer,
std::mem::size_of::<TileUniform>() as u64 * tile.id as u64,
bytemuck::cast_slice(&[TileUniform::new(
std::mem::size_of::<ShaderTileMetadata>() as u64 * tile.id as u64,
bytemuck::cast_slice(&[ShaderTileMetadata::new(
[0.0, 0.0, 0.0, 1.0],
world_coords.into_world(4096.0).into_shader_coords(),
world_coords.into_world(4096.0).into(),
)]),
);
}
@ -379,7 +379,7 @@ impl RenderState {
self.queue.write_buffer(
&self.globals_uniform_buffer,
0,
bytemuck::cast_slice(&[GlobalsUniform::new(
bytemuck::cast_slice(&[ShaderGlobals::new(
self.camera.create_camera_uniform(&self.perspective),
)]),
);
@ -466,8 +466,8 @@ impl RenderState {
pass.set_vertex_buffer(
1,
self.tiles_uniform_buffer.slice(
std::mem::size_of::<TileUniform>() as u64 * id
..std::mem::size_of::<TileUniform>() as u64 * (id + 1),
std::mem::size_of::<ShaderTileMetadata>() as u64 * id
..std::mem::size_of::<ShaderTileMetadata>() as u64 * (id + 1),
),
);
/* if !self.tile_fill_range.is_empty() {

View File

@ -1,108 +0,0 @@
use bytemuck_derive::{Pod, Zeroable};
use cgmath::SquareMatrix;
pub type Vec2f32 = [f32; 2];
pub type Vec3f32 = [f32; 3];
pub type Vec4f32 = [f32; 4];
pub type Mat4f32 = [Vec4f32; 4];
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct CameraUniform {
view_proj: Mat4f32, // 64 bytes
view_position: Vec4f32, // 16 bytes
}
impl CameraUniform {
pub fn new(view_proj: Mat4f32, view_position: Vec4f32) -> Self {
Self {
view_position,
view_proj,
}
}
}
impl Default for CameraUniform {
fn default() -> Self {
Self {
view_position: [0.0; 4],
view_proj: cgmath::Matrix4::identity().into(),
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct GlobalsUniform {
camera: CameraUniform,
}
impl GlobalsUniform {
pub fn new(camera_uniform: CameraUniform) -> Self {
Self {
camera: camera_uniform,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct GpuVertexUniform {
pub position: Vec2f32,
pub normal: Vec2f32,
}
impl GpuVertexUniform {
pub fn new(position: Vec2f32, normal: Vec2f32) -> Self {
Self { position, normal }
}
}
impl Default for GpuVertexUniform {
fn default() -> Self {
GpuVertexUniform::new([0.0, 0.0], [0.0, 0.0])
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct MaskInstanceUniform {
pub position: Vec2f32,
pub target_width: f32,
pub target_height: f32,
pub debug_color: Vec4f32,
}
impl MaskInstanceUniform {
pub fn new(
position: Vec2f32,
target_width: f32,
target_height: f32,
debug_color: Vec4f32,
) -> Self {
Self {
position,
target_width,
target_height,
debug_color,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct TileUniform {
pub color: Vec4f32,
pub translate: Vec3f32,
_pad1: i32, // _padX aligns it to 16 bytes = AlignOf(Vec4f32/vec4<f32>): // https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size
}
impl TileUniform {
pub fn new(color: Vec4f32, translate: Vec3f32) -> Self {
Self {
color,
translate,
_pad1: Default::default(),
}
}
}

View File

@ -1,7 +1,23 @@
use wgpu::{
ColorTargetState, Device, FragmentState, ShaderModule, VertexBufferLayout, VertexState,
ColorTargetState, Device, FragmentState, ShaderModule, VertexBufferLayout, VertexFormat,
VertexState,
};
use crate::coords::WorldCoords;
use bytemuck_derive::{Pod, Zeroable};
use cgmath::SquareMatrix;
pub type Vec2f32 = [f32; 2];
pub type Vec3f32 = [f32; 3];
pub type Vec4f32 = [f32; 4];
pub type Mat4f32 = [Vec4f32; 4];
impl From<WorldCoords> for Vec3f32 {
fn from(world_coords: WorldCoords) -> Self {
[world_coords.x, world_coords.y, world_coords.z]
}
}
pub struct FragmentShaderState {
source: &'static str,
targets: &'static [ColorTargetState],
@ -64,8 +80,8 @@ impl VertexShaderState {
}
pub mod tile {
use super::{ShaderTileMetadata, ShaderVertex};
use crate::platform::COLOR_TEXTURE_FORMAT;
use crate::render::shader_ffi::{GpuVertexUniform, TileUniform};
use super::{FragmentShaderState, VertexShaderState};
@ -73,7 +89,7 @@ pub mod tile {
include_str!("tile.vertex.wgsl"),
&[
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertexUniform>() as u64,
array_stride: std::mem::size_of::<ShaderVertex>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
// position
@ -91,7 +107,7 @@ pub mod tile {
],
},
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<TileUniform>() as u64,
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
// color
@ -122,9 +138,9 @@ pub mod tile {
}
pub mod tile_mask {
use super::ShaderTileMaskInstance;
use crate::platform::COLOR_TEXTURE_FORMAT;
use crate::render::options::DEBUG_STENCIL_PATTERN;
use crate::render::shader_ffi::MaskInstanceUniform;
use wgpu::ColorWrites;
use super::{FragmentShaderState, VertexShaderState};
@ -132,7 +148,7 @@ pub mod tile_mask {
pub const VERTEX: VertexShaderState = VertexShaderState::new(
include_str!("tile_mask.vertex.wgsl"),
&[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<MaskInstanceUniform>() as u64,
array_stride: std::mem::size_of::<ShaderTileMaskInstance>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
// offset position
@ -182,3 +198,104 @@ pub mod tile_mask {
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderCamera {
view_proj: Mat4f32, // 64 bytes
view_position: Vec4f32, // 16 bytes
}
impl ShaderCamera {
pub fn new(view_proj: Mat4f32, view_position: Vec4f32) -> Self {
Self {
view_position,
view_proj,
}
}
}
impl Default for ShaderCamera {
fn default() -> Self {
Self {
view_position: [0.0; 4],
view_proj: cgmath::Matrix4::identity().into(),
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderGlobals {
camera: ShaderCamera,
}
impl ShaderGlobals {
pub fn new(camera_uniform: ShaderCamera) -> Self {
Self {
camera: camera_uniform,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderVertex {
pub position: Vec2f32,
pub normal: Vec2f32,
}
impl ShaderVertex {
pub fn new(position: Vec2f32, normal: Vec2f32) -> Self {
Self { position, normal }
}
}
impl Default for ShaderVertex {
fn default() -> Self {
ShaderVertex::new([0.0, 0.0], [0.0, 0.0])
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderTileMaskInstance {
pub position: Vec2f32,
pub target_width: f32,
pub target_height: f32,
pub debug_color: Vec4f32,
}
impl ShaderTileMaskInstance {
pub fn new(
position: Vec2f32,
target_width: f32,
target_height: f32,
debug_color: Vec4f32,
) -> Self {
Self {
position,
target_width,
target_height,
debug_color,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderTileMetadata {
pub color: Vec4f32,
pub translate: Vec3f32,
_pad1: i32, // _padX aligns it to 16 bytes = AlignOf(Vec4f32/vec4<f32>): // https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size
}
impl ShaderTileMetadata {
pub fn new(color: Vec4f32, translate: Vec3f32) -> Self {
Self {
color,
translate,
_pad1: Default::default(),
}
}
}

View File

@ -1,14 +1,13 @@
struct CameraUniform {
struct ShaderCamera {
view_proj: mat4x4<f32>;
view_position: vec4<f32>;
};
struct GlobalsUniform {
camera: CameraUniform;
struct ShaderGlobals {
camera: ShaderCamera;
};
[[group(0), binding(0)]] var<uniform> globals: GlobalsUniform;
[[group(0), binding(0)]] var<uniform> globals: ShaderGlobals;
struct VertexOutput {
[[location(0)]] v_color: vec4<f32>;

View File

@ -1,14 +1,13 @@
struct CameraUniform {
struct ShaderCamera {
view_proj: mat4x4<f32>;
view_position: vec4<f32>;
};
struct GlobalsUniform {
camera: CameraUniform;
struct ShaderGlobal {
camera: ShaderCamera;
};
[[group(0), binding(0)]] var<uniform> globals: GlobalsUniform;
[[group(0), binding(0)]] var<uniform> globals: ShaderGlobal;
struct VertexOutput {
[[location(0)]] v_color: vec4<f32>;

View File

@ -1,5 +1,5 @@
use crate::coords::WorldTileCoords;
use crate::render::shader_ffi::MaskInstanceUniform;
use crate::render::shaders::ShaderTileMaskInstance;
struct MinMaxBoundingBox {
min_x: i32,
@ -47,7 +47,7 @@ impl MinMaxBoundingBox {
pub struct TileMaskPattern {
bounding_box: MinMaxBoundingBox,
pattern: Vec<MaskInstanceUniform>,
pattern: Vec<ShaderTileMaskInstance>,
}
/// Implementation of a masking algorithm using a stencil buffer. The layout of the
@ -65,7 +65,7 @@ impl TileMaskPattern {
self.bounding_box.update(world_coords)
}
pub fn as_slice(&self) -> &[MaskInstanceUniform] {
pub fn as_slice(&self) -> &[ShaderTileMaskInstance] {
self.pattern.as_slice()
}
@ -75,7 +75,7 @@ impl TileMaskPattern {
fn vertical(&mut self, dx: i32, dy: i32, anchor_x: f32, anchor_y: f32, extent: f32) {
for i in 0..(dx.abs() / 2 + 1) {
self.pattern.push(MaskInstanceUniform::new(
self.pattern.push(ShaderTileMaskInstance::new(
[anchor_x + ((i * 2) + 1) as f32 * extent, anchor_y],
1.0,
dy as f32,
@ -86,7 +86,7 @@ impl TileMaskPattern {
fn horizontal(&mut self, dx: i32, dy: i32, anchor_x: f32, anchor_y: f32, extent: f32) {
for i in 0..(dy.abs() / 2 + 1) {
self.pattern.push(MaskInstanceUniform::new(
self.pattern.push(ShaderTileMaskInstance::new(
[anchor_x, anchor_y + (i * 2) as f32 * extent],
dx as f32,
1.0,
@ -126,7 +126,7 @@ impl TileMaskPattern {
let anchor_x = start_world.x;
let anchor_y = start_world.y;
// red step
self.pattern.push(MaskInstanceUniform::new(
self.pattern.push(ShaderTileMaskInstance::new(
[anchor_x, anchor_y],
dx as f32,
dy as f32,

View File

@ -1,13 +1,12 @@
use bytemuck::Pod;
use std::ops::Add;
use crate::render::ShaderVertex;
use lyon::tessellation::{
FillVertex, FillVertexConstructor, StrokeVertex, StrokeVertexConstructor, VertexBuffers,
};
use wgpu::BufferAddress;
use crate::render::shader_ffi::GpuVertexUniform;
pub mod tile;
const DEFAULT_TOLERANCE: f32 = 0.02;
@ -15,31 +14,32 @@ const DEFAULT_TOLERANCE: f32 = 0.02;
pub type IndexDataType = u16; // Must match INDEX_FORMAT
pub trait Tesselated<I: Add> {
fn tesselate_stroke(&self) -> VertexBuffers<GpuVertexUniform, I>;
fn tesselate_fill(&self) -> VertexBuffers<GpuVertexUniform, I>;
fn tesselate_stroke(&self) -> VertexBuffers<ShaderVertex, I>;
fn tesselate_fill(&self) -> VertexBuffers<ShaderVertex, I>;
fn empty_range(&self) -> VertexBuffers<GpuVertexUniform, I> {
fn empty_range(&self) -> VertexBuffers<ShaderVertex, I> {
VertexBuffers::new()
}
}
pub struct VertexConstructor();
impl FillVertexConstructor<GpuVertexUniform> for VertexConstructor {
fn new_vertex(&mut self, vertex: FillVertex) -> GpuVertexUniform {
GpuVertexUniform::new(vertex.position().to_array(), [0.0, 0.0])
impl FillVertexConstructor<ShaderVertex> for VertexConstructor {
fn new_vertex(&mut self, vertex: FillVertex) -> ShaderVertex {
ShaderVertex::new(vertex.position().to_array(), [0.0, 0.0])
}
}
impl StrokeVertexConstructor<GpuVertexUniform> for VertexConstructor {
fn new_vertex(&mut self, vertex: StrokeVertex) -> GpuVertexUniform {
GpuVertexUniform::new(
impl StrokeVertexConstructor<ShaderVertex> for VertexConstructor {
fn new_vertex(&mut self, vertex: StrokeVertex) -> ShaderVertex {
ShaderVertex::new(
vertex.position_on_path().to_array(),
vertex.normal().to_array(),
)
}
}
/// Vertex buffer which includes additional padding to fulfill the `wgpu::COPY_BUFFER_ALIGNMENT`.
#[derive(Clone)]
pub struct OverAlignedVertexBuffer<V, I> {
pub buffer: VertexBuffers<V, I>,
@ -66,7 +66,7 @@ trait Align<V: Pod, I: Pod> {
impl<V: Pod, I: Pod> Align<V, I> for VertexBuffers<V, I> {
fn align_vertices(&mut self) {
let align = wgpu::COPY_BUFFER_ALIGNMENT;
let stride = std::mem::size_of::<GpuVertexUniform>() as BufferAddress;
let stride = std::mem::size_of::<ShaderVertex>() as BufferAddress;
let unpadded_bytes = self.vertices.len() as BufferAddress * stride;
let padding_bytes = (align - unpadded_bytes % align) % align;

View File

@ -9,10 +9,10 @@ use lyon::tessellation::{
use lyon_path::builder::SvgPathBuilder;
use lyon_path::Path;
use crate::render::ShaderVertex;
use vector_tile::geometry::{Command, Geometry};
use vector_tile::tile::Tile;
use crate::render::shader_ffi::GpuVertexUniform;
use crate::tesselation::{Tesselated, VertexConstructor, DEFAULT_TOLERANCE};
fn build_path(tile: &Tile, fill: bool) -> Path {
@ -85,8 +85,8 @@ fn build_path(tile: &Tile, fill: bool) -> Path {
}
impl<I: Add + From<lyon::lyon_tessellation::VertexId> + MaxIndex + Pod> Tesselated<I> for Tile {
fn tesselate_stroke(&self) -> VertexBuffers<GpuVertexUniform, I> {
let mut buffer: VertexBuffers<GpuVertexUniform, I> = VertexBuffers::new();
fn tesselate_stroke(&self) -> VertexBuffers<ShaderVertex, I> {
let mut buffer: VertexBuffers<ShaderVertex, I> = VertexBuffers::new();
let mut tesselator = StrokeTessellator::new();
let tile_path = build_path(self, false);
@ -102,8 +102,8 @@ impl<I: Add + From<lyon::lyon_tessellation::VertexId> + MaxIndex + Pod> Tesselat
buffer
}
fn tesselate_fill(&self) -> VertexBuffers<GpuVertexUniform, I> {
let mut buffer: VertexBuffers<GpuVertexUniform, I> = VertexBuffers::new();
fn tesselate_fill(&self) -> VertexBuffers<ShaderVertex, I> {
let mut buffer: VertexBuffers<ShaderVertex, I> = VertexBuffers::new();
let mut tesselator = FillTessellator::new();
let tile_path = build_path(self, true);