Rename some functions and revert some changes

This commit is contained in:
Maximilian Ammann 2022-04-01 17:45:24 +02:00
parent d8c2844d3d
commit 7a42abf06d
5 changed files with 204 additions and 249 deletions

View File

@ -1,10 +1,9 @@
use crate::coords::WorldCoords;
use crate::io::tile_cache::TileCache;
use crate::render::render_state::RenderState;
use cgmath::{Vector2};
use cgmath::Vector2;
use log::info;
use std::time::Duration;
use winit::event::{ElementState, MouseButton};

View File

@ -98,7 +98,7 @@ pub async fn run(
scheduler.try_populate_cache();
input.update_state(state, scheduler.get_tile_cache(), dt);
state.upload_tile_geometry(&mut scheduler);
state.prepare_render_data(&mut scheduler);
match state.render() {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost) => {

View File

@ -133,36 +133,32 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
(bytes, aligned_bytes)
}
/// FIXME: use an id instead of layer_name to identify tiles
pub fn get_loaded_layers_at(&self, coords: &WorldTileCoords) -> HashSet<&str> {
if let Some(layers) = self.index.get_layers(coords) {
pub fn get_loaded_layers_at(&self, coords: &WorldTileCoords) -> Option<HashSet<&str>> {
self.index.get_layers(coords).map(|layers| {
layers
.iter()
.map(|entry| entry.style_layer.source_layer.as_ref().unwrap().as_str())
.collect()
} else {
HashSet::new()
}
})
}
/// Allocates
/// * `geometry`
/// * `tile_metadata` and
/// * `feature_metadata` for a tile. This function is able to dynamically evict tiles if there
/// * `layer_metadata` and
/// * `feature_metadata` for a layer. This function is able to dynamically evict layers if there
/// is not enough space available.
pub fn allocate_tile_geometry(
pub fn allocate_layer_geometry(
&mut self,
queue: &Q,
coords: WorldTileCoords,
style_layer: StyleLayer,
geometry: &OverAlignedVertexBuffer<V, I>,
tile_metadata: TM,
layer_metadata: TM,
feature_metadata: &[FM],
empty: bool,
) {
let vertices_stride = size_of::<V>() as wgpu::BufferAddress;
let indices_stride = size_of::<I>() as wgpu::BufferAddress;
let tile_metadata_stride = size_of::<TM>() as wgpu::BufferAddress;
let layer_metadata_stride = size_of::<TM>() as wgpu::BufferAddress;
let feature_metadata_stride = size_of::<FM>() as wgpu::BufferAddress;
let (vertices_bytes, aligned_vertices_bytes) = Self::align(
@ -175,8 +171,8 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
geometry.buffer.indices.len() as BufferAddress,
geometry.usable_indices as BufferAddress,
);
let (tile_metadata_bytes, aligned_tile_metadata_bytes) =
Self::align(tile_metadata_stride, 1, 1);
let (layer_metadata_bytes, aligned_layer_metadata_bytes) =
Self::align(layer_metadata_stride, 1, 1);
let (feature_metadata_bytes, aligned_feature_metadata_bytes) = Self::align(
feature_metadata_stride,
@ -197,63 +193,57 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
buffer_vertices: self.vertices.make_room(vertices_bytes, &mut self.index),
buffer_indices: self.indices.make_room(indices_bytes, &mut self.index),
usable_indices: geometry.usable_indices as u32,
buffer_tile_metadata: self
buffer_layer_metadata: self
.metadata
.make_room(tile_metadata_bytes, &mut self.index),
.make_room(layer_metadata_bytes, &mut self.index),
buffer_feature_metadata: self
.feature_metadata
.make_room(feature_metadata_bytes, &mut self.index),
empty,
};
// write_buffer() is the preferred method for WASM: https://toji.github.io/webgpu-best-practices/buffer-uploads.html#when-in-doubt-writebuffer
if !maybe_entry.buffer_vertices.is_empty() {
queue.write_buffer(
&self.vertices.inner,
maybe_entry.buffer_vertices.start,
&bytemuck::cast_slice(&geometry.buffer.vertices)
[0..aligned_vertices_bytes as usize],
);
}
if !maybe_entry.buffer_indices.is_empty() {
queue.write_buffer(
&self.indices.inner,
maybe_entry.buffer_indices.start,
&bytemuck::cast_slice(&geometry.buffer.indices)[0..aligned_indices_bytes as usize],
);
}
if !maybe_entry.buffer_tile_metadata.is_empty() {
queue.write_buffer(
&self.metadata.inner,
maybe_entry.buffer_tile_metadata.start,
&bytemuck::cast_slice(&[tile_metadata])[0..aligned_tile_metadata_bytes as usize],
);
}
if !maybe_entry.buffer_feature_metadata.is_empty() {
queue.write_buffer(
&self.feature_metadata.inner,
maybe_entry.buffer_feature_metadata.start,
&bytemuck::cast_slice(feature_metadata)[0..aligned_feature_metadata_bytes as usize],
);
}
queue.write_buffer(
&self.vertices.inner,
maybe_entry.buffer_vertices.start,
&bytemuck::cast_slice(&geometry.buffer.vertices)[0..aligned_vertices_bytes as usize],
);
queue.write_buffer(
&self.indices.inner,
maybe_entry.buffer_indices.start,
&bytemuck::cast_slice(&geometry.buffer.indices)[0..aligned_indices_bytes as usize],
);
queue.write_buffer(
&self.metadata.inner,
maybe_entry.buffer_layer_metadata.start,
&bytemuck::cast_slice(&[layer_metadata])[0..aligned_layer_metadata_bytes as usize],
);
queue.write_buffer(
&self.feature_metadata.inner,
maybe_entry.buffer_feature_metadata.start,
&bytemuck::cast_slice(feature_metadata)[0..aligned_feature_metadata_bytes as usize],
);
self.index.push_back(maybe_entry);
}
pub fn update_tile_metadata(&self, queue: &Q, entry: &IndexEntry, tile_metadata: TM) {
let tile_metadata_stride = size_of::<TM>() as wgpu::BufferAddress; // TODO: deduplicate
let (tile_metadata_bytes, aligned_tile_metadata_bytes) =
Self::align(tile_metadata_stride, 1, 1);
pub fn update_layer_metadata(&self, queue: &Q, entry: &IndexEntry, layer_metadata: TM) {
let layer_metadata_stride = size_of::<TM>() as wgpu::BufferAddress; // TODO: deduplicate
let (layer_metadata_bytes, aligned_layer_metadata_bytes) =
Self::align(layer_metadata_stride, 1, 1);
if entry.buffer_tile_metadata.end - entry.buffer_tile_metadata.start != tile_metadata_bytes
if entry.buffer_layer_metadata.end - entry.buffer_layer_metadata.start
!= layer_metadata_bytes
{
panic!("Updated tile metadata has wrong size!");
panic!("Updated layer metadata has wrong size!");
}
queue.write_buffer(
&self.metadata.inner,
entry.buffer_tile_metadata.start,
&bytemuck::cast_slice(&[tile_metadata])[0..aligned_tile_metadata_bytes as usize],
entry.buffer_layer_metadata.start,
&bytemuck::cast_slice(&[layer_metadata])[0..aligned_layer_metadata_bytes as usize],
);
}
@ -320,13 +310,13 @@ impl<B> BackingBuffer<B> {
let start = index.front().map(|first| match self.typ {
BackingBufferType::Vertices => first.buffer_vertices.start,
BackingBufferType::Indices => first.buffer_indices.start,
BackingBufferType::Metadata => first.buffer_tile_metadata.start,
BackingBufferType::Metadata => first.buffer_layer_metadata.start,
BackingBufferType::FeatureMetadata => first.buffer_feature_metadata.start,
});
let end = index.back().map(|first| match self.typ {
BackingBufferType::Vertices => first.buffer_vertices.end,
BackingBufferType::Indices => first.buffer_indices.end,
BackingBufferType::Metadata => first.buffer_tile_metadata.end,
BackingBufferType::Metadata => first.buffer_layer_metadata.end,
BackingBufferType::FeatureMetadata => first.buffer_feature_metadata.end,
});
@ -367,13 +357,12 @@ pub struct IndexEntry {
// Range of bytes within the backing buffer for indices
buffer_indices: Range<wgpu::BufferAddress>,
// Range of bytes within the backing buffer for metadata
buffer_tile_metadata: Range<wgpu::BufferAddress>,
buffer_layer_metadata: Range<wgpu::BufferAddress>,
// Range of bytes within the backing buffer for feature metadata
buffer_feature_metadata: Range<wgpu::BufferAddress>,
// Amount of actually usable indices. Each index has the size/format `IndexDataType`.
// Can be lower than size(buffer_indices) / indices_stride because of alignment.
usable_indices: u32,
pub empty: bool,
}
impl IndexEntry {
@ -389,8 +378,8 @@ impl IndexEntry {
self.buffer_vertices.clone()
}
pub fn tile_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
self.buffer_tile_metadata.clone()
pub fn layer_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
self.buffer_layer_metadata.clone()
}
pub fn feature_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
@ -430,46 +419,26 @@ impl RingIndex {
.and_then(|key| self.tree_index.get(&key))
}
pub fn get_layers_fallback(
&self,
coords: &WorldTileCoords,
) -> Option<(&VecDeque<IndexEntry>, &IndexEntry)> {
pub fn get_layers_fallback(&self, coords: &WorldTileCoords) -> Option<&VecDeque<IndexEntry>> {
let mut current = *coords;
let mut first_mask_entry: Option<&IndexEntry> = None;
loop {
if let Some((entries, mask_entry)) = self
.get_layers(&current)
.map(|entries| (entries, entries.front()))
{
if let Some(mask_entry) = mask_entry {
if let None = first_mask_entry {
first_mask_entry = Some(&mask_entry);
}
if mask_entry.empty {
if let Some(parent) = current.get_parent() {
// Continue with parent because there is no data in current tile
current = parent
} else {
// We do not have a parent tile with actual data, do not render
return None;
}
} else {
// Return actual data
return Some((entries, first_mask_entry.unwrap()));
}
} else {
// No data to we can not draw this tile yet
return None;
}
if let Some(entries) = self.get_layers(&current) {
return Some(entries);
} else if let Some(parent) = current.get_parent() {
current = parent
} else {
// No data to we can not draw this tile yet
return None;
}
}
}
pub fn pop_front(&mut self) -> Option<IndexEntry> {
pub fn iter(&self) -> impl Iterator<Item = &VecDeque<IndexEntry>> + '_ {
self.linear_index
.iter()
.flat_map(|key| self.tree_index.get(key))
}
fn pop_front(&mut self) -> Option<IndexEntry> {
if let Some(entries) = self
.linear_index
.pop_front()
@ -481,7 +450,7 @@ impl RingIndex {
}
}
pub fn push_back(&mut self, entry: IndexEntry) {
fn push_back(&mut self, entry: IndexEntry) {
if let Some(key) = entry.coords.build_quad_key() {
match self.tree_index.entry(key) {
btree_map::Entry::Vacant(index_entry) => {
@ -493,15 +462,9 @@ impl RingIndex {
}
self.linear_index.push_back(key)
} else {
unreachable!() // TODO handle
}
// TODO Else
}
pub fn iter(&self) -> impl Iterator<Item = &VecDeque<IndexEntry>> + '_ {
self.linear_index
.iter()
.flat_map(|key| self.tree_index.get(key))
}
}
@ -567,7 +530,7 @@ mod tests {
let data24bytes_aligned = data24bytes.into();
for _ in 0..2 {
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer.clone(),
@ -581,7 +544,7 @@ mod tests {
pool.available_space(BackingBufferType::Vertices)
);
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer.clone(),
@ -595,7 +558,7 @@ mod tests {
);
println!("{:?}", &pool.index);
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer.clone(),
@ -607,7 +570,7 @@ mod tests {
println!("{:?}", &pool.index);
assert_eq!(24, pool.available_space(BackingBufferType::Vertices));
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer.clone(),
@ -618,7 +581,7 @@ mod tests {
println!("{:?}", &pool.index);
assert_eq!(0, pool.available_space(BackingBufferType::Vertices));
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer.clone(),
@ -629,7 +592,7 @@ mod tests {
println!("{:?}", &pool.index);
assert_eq!(24, pool.available_space(BackingBufferType::Vertices));
pool.allocate_tile_geometry(
pool.allocate_layer_geometry(
&queue,
(0, 0, 0).into(),
style_layer,

View File

@ -16,6 +16,7 @@ use winit::window::Window;
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
use crate::render::buffer_pool::{BackingBufferDescriptor, BufferPool, IndexEntry};
use crate::render::camera;
use crate::render::camera::ViewProjection;
use crate::render::options::{
DEBUG_WIREFRAME, FEATURE_METADATA_BUFFER_SIZE, INDEX_FORMAT, INDICES_BUFFER_SIZE,
TILE_META_COUNT, VERTEX_BUFFER_SIZE,
@ -60,7 +61,7 @@ pub struct RenderState {
Buffer,
ShaderVertex,
IndexDataType,
ShaderTileMetadata,
ShaderLayerMetadata,
ShaderFeatureStyle,
>,
@ -160,7 +161,7 @@ impl RenderState {
cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);
let metadata_buffer_size =
std::mem::size_of::<ShaderTileMetadata>() as u64 * TILE_META_COUNT;
std::mem::size_of::<ShaderLayerMetadata>() as u64 * TILE_META_COUNT;
let metadata_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("Tiles ubo"),
size: metadata_buffer_size,
@ -350,38 +351,27 @@ impl RenderState {
self.zoom.floor() as u8
}
// TODO: Could we draw inspiration from StagingBelt (https://docs.rs/wgpu/latest/wgpu/util/struct.StagingBelt.html)?
// TODO: What is StagingBelt for?
pub fn upload_tile_geometry(&mut self, scheduler: &mut IOScheduler) {
let visible_z = self.visible_z();
/// Fetch tiles which are currently in view
fn fetch_tiles_in_view(&self, view_region: &ViewRegion, scheduler: &mut IOScheduler) {
let source_layers: HashSet<String> = self
.style
.layers
.iter()
.filter_map(|layer| layer.source_layer.clone())
.collect();
let inverted_view_proj = self.camera.calc_view_proj(&self.perspective).invert();
let view_region = self
.camera
.view_region_bounding_box(&inverted_view_proj)
.map(|bounding_box| ViewRegion::new(bounding_box, 2, self.zoom, visible_z));
// Fetch tiles which are currently in view
if let Some(view_region) = &view_region {
let source_layers: HashSet<String> = self
.style
.layers
.iter()
.filter_map(|layer| layer.source_layer.clone())
.collect();
for coords in view_region.iter() {
if let Some(_) = coords.build_quad_key() {
scheduler.try_request_tile(&coords, &source_layers).unwrap();
}
for coords in view_region.iter() {
if let Some(_) = coords.build_quad_key() {
// TODO: Make tesselation depend on style?
scheduler.try_request_tile(&coords, &source_layers).unwrap();
}
}
}
let view_proj = self.camera.calc_view_proj(&self.perspective);
// Update tile metadata for all required tiles on the GPU according to current zoom, camera and perspective
// We perform the update before uploading new tessellated tiles, such that each
// tile metadata in the the `buffer_pool` gets updated exactly once and not twice.
/// Update tile metadata for all required tiles on the GPU according to current zoom, camera and perspective
/// We perform the update before uploading new tessellated tiles, such that each
/// tile metadata in the the `buffer_pool` gets updated exactly once and not twice.
fn update_metadata(&self, view_proj: &ViewProjection) {
for entries in self.buffer_pool.index().iter() {
for entry in entries {
let world_coords = entry.coords;
@ -394,10 +384,12 @@ impl RenderState {
.to_model_view_projection(world_coords.transform_for_zoom(self.zoom)))
.downcast();
self.buffer_pool.update_tile_metadata(
// TODO: Update features
self.buffer_pool.update_layer_metadata(
&self.queue,
entry,
ShaderTileMetadata::new(
ShaderLayerMetadata::new(
transform.into(),
zoom_factor,
entry.style_layer.index as f32,
@ -405,110 +397,115 @@ impl RenderState {
);
}
}
}
fn upload_tile_geometry(
&mut self,
view_proj: &ViewProjection,
view_region: &ViewRegion,
scheduler: &mut IOScheduler,
) {
let visible_z = self.visible_z();
// Factor which determines how much we need to adjust the width of lines for example.
// If zoom == z -> zoom_factor == 1
let zoom_factor = 2.0_f64.powf(visible_z as f64 - self.zoom) as f32; // TODO deduplicate
// Upload all tessellated layers which are in view
if let Some(view_region) = &view_region {
for world_coords in view_region.iter() {
let loaded_layers = self.buffer_pool.get_loaded_layers_at(&world_coords);
for world_coords in view_region.iter() {
let loaded_layers = self
.buffer_pool
.get_loaded_layers_at(&world_coords)
.unwrap_or_default();
if let Some(available_layers) = scheduler
.get_tile_cache()
.iter_tessellated_layers_at(&world_coords, &loaded_layers)
.map(|layers| layers.collect::<Vec<_>>())
{
for style_layer in &self.style.layers {
let source_layer = style_layer.source_layer.as_ref().unwrap();
if let Some(available_layers) = scheduler
.get_tile_cache()
.iter_tessellated_layers_at(&world_coords, &loaded_layers)
.map(|layers| layers.collect::<Vec<_>>())
{
for style_layer in &self.style.layers {
let source_layer = style_layer.source_layer.as_ref().unwrap();
if let Some(result) = available_layers
.iter()
.find(|layer| source_layer.as_str() == layer.layer_name())
{
let color: Option<Vec4f32> = style_layer
.paint
.as_ref()
.and_then(|paint| paint.get_color())
.map(|color| color.into());
if let Some(result) = available_layers
.iter()
.find(|layer| source_layer.as_str() == layer.layer_name())
{
let color: Option<Vec4f32> = style_layer
.paint
.as_ref()
.and_then(|paint| paint.get_color())
.map(|color| color.into());
match result {
LayerTessellateResult::UnavailableLayer { coords, .. } => {
/*self.buffer_pool.mark_layer_unavailable(*coords);*/
}
LayerTessellateResult::TessellatedLayer {
coords,
feature_indices,
layer_data,
buffer,
..
} => {
let world_coords = coords;
match result {
LayerTessellateResult::UnavailableLayer { coords, .. } => {
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
// better supported.
let transform: Matrix4<f32> = (view_proj
.to_model_view_projection(
world_coords.transform_for_zoom(self.zoom),
))
.downcast();
let tile_metadata = ShaderTileMetadata::new(
transform.into(),
zoom_factor,
style_layer.index as f32,
);
println!("unavailable layer");
self.buffer_pool.allocate_tile_geometry(
&self.queue,
*coords,
style_layer.clone(),
&OverAlignedVertexBuffer::empty(),
tile_metadata,
&[],
true,
);
}
LayerTessellateResult::TessellatedLayer {
coords,
feature_indices,
layer_data,
buffer,
..
} => {
let world_coords = coords;
let feature_metadata = layer_data
.features()
.iter()
.enumerate()
.flat_map(|(i, _feature)| {
iter::repeat(ShaderFeatureStyle {
color: color.unwrap(),
})
.take(feature_indices[i] as usize)
let feature_metadata = layer_data
.features()
.iter()
.enumerate()
.flat_map(|(i, _feature)| {
iter::repeat(ShaderFeatureStyle {
color: color.unwrap(),
})
.collect::<Vec<_>>();
.take(feature_indices[i] as usize)
})
.collect::<Vec<_>>();
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
// better supported.
let transform: Matrix4<f32> = (view_proj
.to_model_view_projection(
world_coords.transform_for_zoom(self.zoom),
))
.downcast();
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
// better supported.
let transform: Matrix4<f32> = (view_proj.to_model_view_projection(
world_coords.transform_for_zoom(self.zoom),
))
.downcast();
let tile_metadata = ShaderTileMetadata::new(
self.buffer_pool.allocate_layer_geometry(
&self.queue,
*coords,
style_layer.clone(),
buffer,
ShaderLayerMetadata::new(
transform.into(),
zoom_factor,
style_layer.index as f32,
);
self.buffer_pool.allocate_tile_geometry(
&self.queue,
*coords,
style_layer.clone(),
buffer,
tile_metadata,
&feature_metadata,
false,
);
}
),
&feature_metadata,
);
}
}
}
}
}
}
}
pub fn prepare_render_data(&mut self, scheduler: &mut IOScheduler) {
let visible_z = self.visible_z();
let view_region = self
.camera
.view_region_bounding_box(&self.camera.calc_view_proj(&self.perspective).invert())
.map(|bounding_box| ViewRegion::new(bounding_box, 2, self.zoom, visible_z));
let view_proj = self.camera.calc_view_proj(&self.perspective);
self.update_metadata(&view_proj);
if let Some(view_region) = &view_region {
self.upload_tile_geometry(&view_proj, &view_region, scheduler);
self.fetch_tiles_in_view(view_region, scheduler);
}
// TODO: Could we draw inspiration from StagingBelt (https://docs.rs/wgpu/latest/wgpu/util/struct.StagingBelt.html)?
// TODO: What is StagingBelt for?
// Update globals
self.queue.write_buffer(
@ -587,9 +584,7 @@ impl RenderState {
for world_coords in view_region.iter() {
/* println!("Render coordinate {:?}", world_coords);*/
if let Some((entries, mask_entry)) =
index.get_layers_fallback(&world_coords)
{
if let Some(entries) = index.get_layers_fallback(&world_coords) {
let mut to_render: Vec<&IndexEntry> = Vec::from_iter(entries);
to_render.sort_by_key(|entry| entry.style_layer.index);
@ -601,23 +596,21 @@ impl RenderState {
/* println!("Render mask");*/
// Draw mask
{
pass.set_pipeline(&self.mask_pipeline);
pass.set_stencil_reference(reference);
pass.set_vertex_buffer(
0,
self.buffer_pool
.metadata()
.slice(mask_entry.tile_metadata_buffer_range()),
);
pass.draw(0..6, 0..1);
if let Some(mask_entry) = entries.front() {
{
pass.set_pipeline(&self.mask_pipeline);
pass.set_stencil_reference(reference);
pass.set_vertex_buffer(
0,
self.buffer_pool
.metadata()
.slice(mask_entry.layer_metadata_buffer_range()),
);
pass.draw(0..6, 0..1);
}
}
for entry in to_render {
if entry.empty {
continue;
}
// Draw tile
{
/* println!("Render tile");*/
@ -640,7 +633,7 @@ impl RenderState {
1,
self.buffer_pool
.metadata()
.slice(entry.tile_metadata_buffer_range()),
.slice(entry.layer_metadata_buffer_range()),
);
pass.set_vertex_buffer(
2,

View File

@ -80,7 +80,7 @@ impl VertexShaderState {
}
pub mod tile {
use super::{ShaderTileMetadata, ShaderVertex};
use super::{ShaderLayerMetadata, ShaderVertex};
use crate::platform::COLOR_TEXTURE_FORMAT;
use crate::render::shaders::ShaderFeatureStyle;
@ -110,7 +110,7 @@ pub mod tile {
},
// tile metadata
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
array_stride: std::mem::size_of::<ShaderLayerMetadata>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
// translate
@ -188,7 +188,7 @@ pub mod tile {
pub mod tile_mask {
use crate::platform::COLOR_TEXTURE_FORMAT;
use crate::render::options::DEBUG_STENCIL_PATTERN;
use crate::render::shaders::ShaderTileMetadata;
use crate::render::shaders::ShaderLayerMetadata;
use wgpu::ColorWrites;
use super::{FragmentShaderState, VertexShaderState};
@ -196,7 +196,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::<ShaderTileMetadata>() as u64,
array_stride: std::mem::size_of::<ShaderLayerMetadata>() as u64,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &[
// translate
@ -308,13 +308,13 @@ pub struct ShaderFeatureStyle {
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderTileMetadata {
pub struct ShaderLayerMetadata {
pub transform: Mat4x4f32,
pub zoom_factor: f32,
pub z_index: f32,
}
impl ShaderTileMetadata {
impl ShaderLayerMetadata {
pub fn new(transform: Mat4x4f32, zoom_factor: f32, z_index: f32) -> Self {
Self {
transform,