mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Add feature metadata
This commit is contained in:
parent
635df81f1c
commit
e044b81a72
@ -23,16 +23,18 @@ impl Queue<wgpu::Buffer> for wgpu::Queue {
|
|||||||
/// This is inspired by the memory pool in Vulkan documented
|
/// This is inspired by the memory pool in Vulkan documented
|
||||||
/// [here](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/custom_memory_pools.html).
|
/// [here](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/custom_memory_pools.html).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BufferPool<Q, B, V, I, M> {
|
pub struct BufferPool<Q, B, V, I, M, FM> {
|
||||||
vertices: BackingBuffer<B>,
|
vertices: BackingBuffer<B>,
|
||||||
indices: BackingBuffer<B>,
|
indices: BackingBuffer<B>,
|
||||||
metadata: BackingBuffer<B>,
|
metadata: BackingBuffer<B>,
|
||||||
|
feature_metadata: BackingBuffer<B>,
|
||||||
|
|
||||||
pub index: VecDeque<IndexEntry>,
|
pub index: VecDeque<IndexEntry>,
|
||||||
phantom_v: PhantomData<V>,
|
phantom_v: PhantomData<V>,
|
||||||
phantom_i: PhantomData<I>,
|
phantom_i: PhantomData<I>,
|
||||||
phantom_q: PhantomData<Q>,
|
phantom_q: PhantomData<Q>,
|
||||||
phantom_m: PhantomData<M>,
|
phantom_m: PhantomData<M>,
|
||||||
|
phantom_fm: PhantomData<FM>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -40,15 +42,17 @@ enum BackingBufferType {
|
|||||||
VERTICES,
|
VERTICES,
|
||||||
INDICES,
|
INDICES,
|
||||||
METADATA,
|
METADATA,
|
||||||
|
FEATURE_METADATA,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod, FM: bytemuck::Pod>
|
||||||
BufferPool<Q, B, V, I, M>
|
BufferPool<Q, B, V, I, M, FM>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
vertices: BackingBufferDescriptor<B>,
|
vertices: BackingBufferDescriptor<B>,
|
||||||
indices: BackingBufferDescriptor<B>,
|
indices: BackingBufferDescriptor<B>,
|
||||||
metadata: BackingBufferDescriptor<B>,
|
metadata: BackingBufferDescriptor<B>,
|
||||||
|
feature_metadata: BackingBufferDescriptor<B>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
vertices: BackingBuffer::new(
|
vertices: BackingBuffer::new(
|
||||||
@ -66,11 +70,17 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
metadata.inner_size,
|
metadata.inner_size,
|
||||||
BackingBufferType::METADATA,
|
BackingBufferType::METADATA,
|
||||||
),
|
),
|
||||||
|
feature_metadata: BackingBuffer::new(
|
||||||
|
feature_metadata.buffer,
|
||||||
|
feature_metadata.inner_size,
|
||||||
|
BackingBufferType::FEATURE_METADATA,
|
||||||
|
),
|
||||||
index: VecDeque::new(), // TODO: Approximate amount of buffers in pool
|
index: VecDeque::new(), // TODO: Approximate amount of buffers in pool
|
||||||
phantom_v: Default::default(),
|
phantom_v: Default::default(),
|
||||||
phantom_i: Default::default(),
|
phantom_i: Default::default(),
|
||||||
phantom_q: Default::default(),
|
phantom_q: Default::default(),
|
||||||
phantom_m: Default::default(),
|
phantom_m: Default::default(),
|
||||||
|
phantom_fm: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +90,7 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
BackingBufferType::VERTICES => &self.vertices,
|
BackingBufferType::VERTICES => &self.vertices,
|
||||||
BackingBufferType::INDICES => &self.indices,
|
BackingBufferType::INDICES => &self.indices,
|
||||||
BackingBufferType::METADATA => &self.metadata,
|
BackingBufferType::METADATA => &self.metadata,
|
||||||
|
BackingBufferType::FEATURE_METADATA => &self.feature_metadata,
|
||||||
}
|
}
|
||||||
.find_largest_gap(&self.index);
|
.find_largest_gap(&self.index);
|
||||||
|
|
||||||
@ -98,6 +109,10 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
&self.metadata.inner
|
&self.metadata.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn feature_metadata(&self) -> &B {
|
||||||
|
&self.feature_metadata.inner
|
||||||
|
}
|
||||||
|
|
||||||
/// The VertexBuffers can contain padding elements. Not everything from a VertexBuffers is useable.
|
/// The VertexBuffers can contain padding elements. Not everything from a VertexBuffers is useable.
|
||||||
/// The function returns the `bytes` and `aligned_bytes`. See [`OverAlignedVertexBuffer`].
|
/// The function returns the `bytes` and `aligned_bytes`. See [`OverAlignedVertexBuffer`].
|
||||||
fn align(
|
fn align(
|
||||||
@ -121,14 +136,15 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
pub fn allocate_geometry(
|
pub fn allocate_geometry(
|
||||||
&mut self,
|
&mut self,
|
||||||
queue: &Q,
|
queue: &Q,
|
||||||
id: u32,
|
|
||||||
coords: TileCoords,
|
coords: TileCoords,
|
||||||
over_aligned: &OverAlignedVertexBuffer<V, I>,
|
over_aligned: &OverAlignedVertexBuffer<V, I>,
|
||||||
metadata: M,
|
metadata: M,
|
||||||
|
feature_metadata: &Vec<FM>,
|
||||||
) {
|
) {
|
||||||
let vertices_stride = size_of::<V>() as wgpu::BufferAddress;
|
let vertices_stride = size_of::<V>() as wgpu::BufferAddress;
|
||||||
let indices_stride = size_of::<I>() as wgpu::BufferAddress;
|
let indices_stride = size_of::<I>() as wgpu::BufferAddress;
|
||||||
let metadata_stride = size_of::<M>() as wgpu::BufferAddress;
|
let metadata_stride = size_of::<M>() as wgpu::BufferAddress;
|
||||||
|
let feature_metadata_stride = size_of::<FM>() as wgpu::BufferAddress;
|
||||||
|
|
||||||
let (vertices_bytes, aligned_vertices_bytes) = Self::align(
|
let (vertices_bytes, aligned_vertices_bytes) = Self::align(
|
||||||
vertices_stride,
|
vertices_stride,
|
||||||
@ -141,14 +157,28 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
over_aligned.usable_indices as BufferAddress,
|
over_aligned.usable_indices as BufferAddress,
|
||||||
);
|
);
|
||||||
let (metadata_bytes, aligned_metadata_bytes) = Self::align(metadata_stride, 1, 1);
|
let (metadata_bytes, aligned_metadata_bytes) = Self::align(metadata_stride, 1, 1);
|
||||||
|
let (feature_metadata_bytes, aligned_feature_metadata_bytes) = Self::align(
|
||||||
|
feature_metadata_stride,
|
||||||
|
feature_metadata.len() as BufferAddress,
|
||||||
|
feature_metadata.len() as BufferAddress,
|
||||||
|
);
|
||||||
|
|
||||||
|
if feature_metadata_bytes != aligned_feature_metadata_bytes {
|
||||||
|
// FIXME: align if not aligned?
|
||||||
|
panic!(
|
||||||
|
"feature_metadata is not aligned. This should not happen as long as size_of::<FM>() is a multiple of the alignment."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let maybe_entry = IndexEntry {
|
let maybe_entry = IndexEntry {
|
||||||
id,
|
|
||||||
coords,
|
coords,
|
||||||
buffer_vertices: self.vertices.make_room(vertices_bytes, &mut self.index),
|
buffer_vertices: self.vertices.make_room(vertices_bytes, &mut self.index),
|
||||||
buffer_indices: self.indices.make_room(indices_bytes, &mut self.index),
|
buffer_indices: self.indices.make_room(indices_bytes, &mut self.index),
|
||||||
usable_indices: over_aligned.usable_indices as u32,
|
usable_indices: over_aligned.usable_indices as u32,
|
||||||
buffer_metadata: self.metadata.make_room(metadata_bytes, &mut self.index),
|
buffer_metadata: self.metadata.make_room(metadata_bytes, &mut self.index),
|
||||||
|
buffer_feature_metadata: self
|
||||||
|
.feature_metadata
|
||||||
|
.make_room(feature_metadata_bytes, &mut self.index),
|
||||||
};
|
};
|
||||||
|
|
||||||
// write_buffer() is the preferred method for WASM: https://toji.github.io/webgpu-best-practices/buffer-uploads.html#when-in-doubt-writebuffer
|
// write_buffer() is the preferred method for WASM: https://toji.github.io/webgpu-best-practices/buffer-uploads.html#when-in-doubt-writebuffer
|
||||||
@ -168,6 +198,12 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
|||||||
maybe_entry.buffer_metadata.start,
|
maybe_entry.buffer_metadata.start,
|
||||||
&bytemuck::cast_slice(&[metadata])[0..aligned_metadata_bytes as usize],
|
&bytemuck::cast_slice(&[metadata])[0..aligned_metadata_bytes as usize],
|
||||||
);
|
);
|
||||||
|
queue.write_buffer(
|
||||||
|
&self.feature_metadata.inner,
|
||||||
|
maybe_entry.buffer_feature_metadata.start,
|
||||||
|
&bytemuck::cast_slice(feature_metadata.as_slice())
|
||||||
|
[0..aligned_feature_metadata_bytes as usize],
|
||||||
|
);
|
||||||
self.index.push_back(maybe_entry);
|
self.index.push_back(maybe_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,11 +271,13 @@ impl<B> BackingBuffer<B> {
|
|||||||
BackingBufferType::VERTICES => first.buffer_vertices.start,
|
BackingBufferType::VERTICES => first.buffer_vertices.start,
|
||||||
BackingBufferType::INDICES => first.buffer_indices.start,
|
BackingBufferType::INDICES => first.buffer_indices.start,
|
||||||
BackingBufferType::METADATA => first.buffer_metadata.start,
|
BackingBufferType::METADATA => first.buffer_metadata.start,
|
||||||
|
BackingBufferType::FEATURE_METADATA => first.buffer_feature_metadata.start,
|
||||||
});
|
});
|
||||||
let end = index.back().map(|first| match self.typ {
|
let end = index.back().map(|first| match self.typ {
|
||||||
BackingBufferType::VERTICES => first.buffer_vertices.end,
|
BackingBufferType::VERTICES => first.buffer_vertices.end,
|
||||||
BackingBufferType::INDICES => first.buffer_indices.end,
|
BackingBufferType::INDICES => first.buffer_indices.end,
|
||||||
BackingBufferType::METADATA => first.buffer_metadata.end,
|
BackingBufferType::METADATA => first.buffer_metadata.end,
|
||||||
|
BackingBufferType::FEATURE_METADATA => first.buffer_feature_metadata.end,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(start) = start {
|
if let Some(start) = start {
|
||||||
@ -272,7 +310,6 @@ impl<B> BackingBuffer<B> {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IndexEntry {
|
pub struct IndexEntry {
|
||||||
pub id: u32,
|
|
||||||
pub coords: TileCoords,
|
pub coords: TileCoords,
|
||||||
// Range of bytes within the backing buffer for vertices
|
// Range of bytes within the backing buffer for vertices
|
||||||
buffer_vertices: Range<wgpu::BufferAddress>,
|
buffer_vertices: Range<wgpu::BufferAddress>,
|
||||||
@ -280,6 +317,8 @@ pub struct IndexEntry {
|
|||||||
buffer_indices: Range<wgpu::BufferAddress>,
|
buffer_indices: Range<wgpu::BufferAddress>,
|
||||||
// Range of bytes within the backing buffer for metadata
|
// Range of bytes within the backing buffer for metadata
|
||||||
buffer_metadata: Range<wgpu::BufferAddress>,
|
buffer_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`.
|
// Amount of actually usable indices. Each index has the size/format `IndexDataType`.
|
||||||
// Can be lower than size(buffer_indices) / indices_stride because of alignment.
|
// Can be lower than size(buffer_indices) / indices_stride because of alignment.
|
||||||
usable_indices: u32,
|
usable_indices: u32,
|
||||||
@ -301,6 +340,10 @@ impl IndexEntry {
|
|||||||
pub fn metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
pub fn metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||||
self.buffer_metadata.clone()
|
self.buffer_metadata.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn feature_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||||
|
self.buffer_feature_metadata.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use std::cmp;
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::{cmp, iter};
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
use vector_tile::tile::Layer;
|
||||||
use wgpu::{Buffer, BufferAddress, Limits, Queue};
|
use wgpu::{Buffer, BufferAddress, Limits, Queue};
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
@ -10,6 +11,10 @@ use crate::io::worker_loop::WorkerLoop;
|
|||||||
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
|
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
|
||||||
use crate::render::buffer_pool::{BackingBufferDescriptor, BufferPool};
|
use crate::render::buffer_pool::{BackingBufferDescriptor, BufferPool};
|
||||||
use crate::render::camera;
|
use crate::render::camera;
|
||||||
|
use crate::render::options::{
|
||||||
|
DEBUG_WIREFRAME, FEATURE_METADATA_BUFFER_SIZE, INDEX_FORMAT, INDICES_BUFFER_SIZE,
|
||||||
|
TILE_MASK_INSTANCE_COUNT, TILE_META_COUNT, VERTEX_BUFFER_SIZE,
|
||||||
|
};
|
||||||
use crate::render::tile_mask_pattern::TileMaskPattern;
|
use crate::render::tile_mask_pattern::TileMaskPattern;
|
||||||
use crate::tesselation::IndexDataType;
|
use crate::tesselation::IndexDataType;
|
||||||
use crate::util::FPSMeter;
|
use crate::util::FPSMeter;
|
||||||
@ -19,12 +24,6 @@ use super::shaders;
|
|||||||
use super::shaders::*;
|
use super::shaders::*;
|
||||||
use super::texture::Texture;
|
use super::texture::Texture;
|
||||||
|
|
||||||
const INDEX_FORMAT: wgpu::IndexFormat = wgpu::IndexFormat::Uint16; // Must match IndexDataType
|
|
||||||
const VERTEX_BUFFER_SIZE: BufferAddress = 1024 * 1024 * 8;
|
|
||||||
const INDICES_BUFFER_SIZE: BufferAddress = 1024 * 1024 * 8;
|
|
||||||
const TILE_META_COUNT: BufferAddress = 1024 * 8; // FIXME: Move this to BufferPool
|
|
||||||
const TILE_MASK_INSTANCE_COUNT: BufferAddress = 512; // FIXME: Pick reasonable size
|
|
||||||
|
|
||||||
pub struct RenderState {
|
pub struct RenderState {
|
||||||
instance: wgpu::Instance,
|
instance: wgpu::Instance,
|
||||||
|
|
||||||
@ -50,7 +49,14 @@ pub struct RenderState {
|
|||||||
|
|
||||||
globals_uniform_buffer: wgpu::Buffer,
|
globals_uniform_buffer: wgpu::Buffer,
|
||||||
|
|
||||||
buffer_pool: BufferPool<Queue, Buffer, ShaderVertex, IndexDataType, ShaderTileMetadata>,
|
buffer_pool: BufferPool<
|
||||||
|
Queue,
|
||||||
|
Buffer,
|
||||||
|
ShaderVertex,
|
||||||
|
IndexDataType,
|
||||||
|
ShaderTileMetadata,
|
||||||
|
ShaderFeatureStyle,
|
||||||
|
>,
|
||||||
|
|
||||||
tile_mask_pattern: TileMaskPattern,
|
tile_mask_pattern: TileMaskPattern,
|
||||||
tile_mask_instances_buffer: wgpu::Buffer,
|
tile_mask_instances_buffer: wgpu::Buffer,
|
||||||
@ -103,11 +109,17 @@ impl RenderState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// create a device and a queue
|
// create a device and a queue
|
||||||
|
let features = if DEBUG_WIREFRAME {
|
||||||
|
wgpu::Features::default() | wgpu::Features::POLYGON_MODE_LINE
|
||||||
|
} else {
|
||||||
|
wgpu::Features::default()
|
||||||
|
};
|
||||||
|
|
||||||
let (device, queue) = adapter
|
let (device, queue) = adapter
|
||||||
.request_device(
|
.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
features: wgpu::Features::default(),
|
features,
|
||||||
limits,
|
limits,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
@ -115,26 +127,33 @@ impl RenderState {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let vertex_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: VERTEX_BUFFER_SIZE,
|
size: VERTEX_BUFFER_SIZE,
|
||||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let indices_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let feature_metadata_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
label: None,
|
||||||
|
size: FEATURE_METADATA_BUFFER_SIZE,
|
||||||
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
|
mapped_at_creation: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let indices_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: INDICES_BUFFER_SIZE,
|
size: INDICES_BUFFER_SIZE,
|
||||||
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let tile_masks_uniform_buffer_size =
|
let tile_masks_instances_buffer_size =
|
||||||
std::mem::size_of::<ShaderTileMaskInstance>() 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 {
|
let tile_mask_instances = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: tile_masks_uniform_buffer_size,
|
size: tile_masks_instances_buffer_size,
|
||||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
@ -142,11 +161,11 @@ impl RenderState {
|
|||||||
let globals_buffer_byte_size =
|
let globals_buffer_byte_size =
|
||||||
cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);
|
cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);
|
||||||
|
|
||||||
let tiles_uniform_buffer_size =
|
let metadata_buffer_size =
|
||||||
std::mem::size_of::<ShaderTileMetadata>() as u64 * TILE_META_COUNT;
|
std::mem::size_of::<ShaderTileMetadata>() as u64 * TILE_META_COUNT;
|
||||||
let tiles_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
let metadata_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: Some("Tiles ubo"),
|
label: Some("Tiles ubo"),
|
||||||
size: tiles_uniform_buffer_size,
|
size: metadata_buffer_size,
|
||||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
@ -273,9 +292,10 @@ impl RenderState {
|
|||||||
perspective: projection,
|
perspective: projection,
|
||||||
suspended: false, // Initially the app is not suspended
|
suspended: false, // Initially the app is not suspended
|
||||||
buffer_pool: BufferPool::new(
|
buffer_pool: BufferPool::new(
|
||||||
BackingBufferDescriptor::new(vertex_uniform_buffer, VERTEX_BUFFER_SIZE),
|
BackingBufferDescriptor::new(vertex_buffer, VERTEX_BUFFER_SIZE),
|
||||||
BackingBufferDescriptor::new(indices_uniform_buffer, INDICES_BUFFER_SIZE),
|
BackingBufferDescriptor::new(indices_buffer, INDICES_BUFFER_SIZE),
|
||||||
BackingBufferDescriptor::new(tiles_uniform_buffer, tiles_uniform_buffer_size),
|
BackingBufferDescriptor::new(metadata_buffer, metadata_buffer_size),
|
||||||
|
BackingBufferDescriptor::new(feature_metadata_buffer, FEATURE_METADATA_BUFFER_SIZE),
|
||||||
),
|
),
|
||||||
tile_mask_pattern: TileMaskPattern::new(),
|
tile_mask_pattern: TileMaskPattern::new(),
|
||||||
}
|
}
|
||||||
@ -332,19 +352,47 @@ impl RenderState {
|
|||||||
pub fn upload_tile_geometry(&mut self, worker_loop: &WorkerLoop) {
|
pub fn upload_tile_geometry(&mut self, worker_loop: &WorkerLoop) {
|
||||||
let upload = worker_loop.pop_all();
|
let upload = worker_loop.pop_all();
|
||||||
|
|
||||||
for tile in upload.iter() {
|
for layer in upload.iter() {
|
||||||
let world_coords = tile.coords.into_world_tile();
|
let world_coords = layer.coords.into_world_tile();
|
||||||
self.tile_mask_pattern.update_bounds(&world_coords);
|
self.tile_mask_pattern.update_bounds(&world_coords);
|
||||||
|
|
||||||
|
/*match tile.layer_data.name() {
|
||||||
|
"transportation" => {}
|
||||||
|
"building" => {}
|
||||||
|
"boundary" => {}
|
||||||
|
"water" => {}
|
||||||
|
"waterway" => {}
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
|
||||||
|
let feature_metadata = layer
|
||||||
|
.layer_data
|
||||||
|
.features()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(i, feature)| {
|
||||||
|
iter::repeat(ShaderFeatureStyle {
|
||||||
|
color: match layer.layer_data.name() {
|
||||||
|
"transportation" => [1.0, 0.0, 0.0, 1.0],
|
||||||
|
"building" => [0.0, 1.0, 1.0, 1.0],
|
||||||
|
"boundary" => [0.0, 0.0, 0.0, 1.0],
|
||||||
|
"water" => [0.0, 0.0, 1.0, 1.0],
|
||||||
|
"waterway" => [0.0, 0.0, 1.0, 1.0],
|
||||||
|
_ => [0.0, 0.0, 0.0, 0.0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.take(*layer.feature_vertices.get(i).unwrap() as usize)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.buffer_pool.allocate_geometry(
|
self.buffer_pool.allocate_geometry(
|
||||||
&self.queue,
|
&self.queue,
|
||||||
tile.id,
|
layer.coords,
|
||||||
tile.coords,
|
&layer.buffer,
|
||||||
&tile.over_aligned,
|
ShaderTileMetadata::new(world_coords.into_world(4096.0).into()),
|
||||||
ShaderTileMetadata::new(
|
&feature_metadata,
|
||||||
[0.0, 0.0, 0.0, 1.0],
|
|
||||||
world_coords.into_world(4096.0).into(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,18 +490,18 @@ impl RenderState {
|
|||||||
.vertices()
|
.vertices()
|
||||||
.slice(entry.vertices_buffer_range()),
|
.slice(entry.vertices_buffer_range()),
|
||||||
);
|
);
|
||||||
let id = entry.id as BufferAddress;
|
|
||||||
pass.set_vertex_buffer(
|
pass.set_vertex_buffer(
|
||||||
1,
|
1,
|
||||||
self.buffer_pool
|
self.buffer_pool
|
||||||
.metadata()
|
.metadata()
|
||||||
.slice(entry.metadata_buffer_range()),
|
.slice(entry.metadata_buffer_range()),
|
||||||
);
|
);
|
||||||
/* if !self.tile_fill_range.is_empty() {
|
pass.set_vertex_buffer(
|
||||||
pass.draw_indexed(self.tile_fill_range.clone(), 0, 0..1);
|
2,
|
||||||
}*/
|
self.buffer_pool
|
||||||
trace!("current buffer_pool index {:?}", self.buffer_pool.index);
|
.feature_metadata()
|
||||||
// FIXME: Custom Instance index possibly breaks on Metal
|
.slice(entry.feature_metadata_buffer_range()),
|
||||||
|
);
|
||||||
pass.draw_indexed(entry.indices_range(), 0, 0..1);
|
pass.draw_indexed(entry.indices_range(), 0, 0..1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,12 +81,14 @@ impl VertexShaderState {
|
|||||||
pub mod tile {
|
pub mod tile {
|
||||||
use super::{ShaderTileMetadata, ShaderVertex};
|
use super::{ShaderTileMetadata, ShaderVertex};
|
||||||
use crate::platform::COLOR_TEXTURE_FORMAT;
|
use crate::platform::COLOR_TEXTURE_FORMAT;
|
||||||
|
use wgpu::BlendState;
|
||||||
|
|
||||||
use super::{FragmentShaderState, VertexShaderState};
|
use super::{FragmentShaderState, VertexShaderState};
|
||||||
|
|
||||||
pub const VERTEX: VertexShaderState = VertexShaderState::new(
|
pub const VERTEX: VertexShaderState = VertexShaderState::new(
|
||||||
include_str!("tile.vertex.wgsl"),
|
include_str!("tile.vertex.wgsl"),
|
||||||
&[
|
&[
|
||||||
|
// vertex data
|
||||||
wgpu::VertexBufferLayout {
|
wgpu::VertexBufferLayout {
|
||||||
array_stride: std::mem::size_of::<ShaderVertex>() as u64,
|
array_stride: std::mem::size_of::<ShaderVertex>() as u64,
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
@ -105,21 +107,29 @@ pub mod tile {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// tile metadata
|
||||||
wgpu::VertexBufferLayout {
|
wgpu::VertexBufferLayout {
|
||||||
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
||||||
step_mode: wgpu::VertexStepMode::Instance,
|
step_mode: wgpu::VertexStepMode::Instance,
|
||||||
|
attributes: &[
|
||||||
|
// translate
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
offset: 0,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
shader_location: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// vertex style
|
||||||
|
wgpu::VertexBufferLayout {
|
||||||
|
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
||||||
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
attributes: &[
|
attributes: &[
|
||||||
// color
|
// color
|
||||||
wgpu::VertexAttribute {
|
wgpu::VertexAttribute {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
format: wgpu::VertexFormat::Float32x4,
|
format: wgpu::VertexFormat::Float32x4,
|
||||||
shader_location: 3,
|
shader_location: 5,
|
||||||
},
|
|
||||||
// translate
|
|
||||||
wgpu::VertexAttribute {
|
|
||||||
offset: wgpu::VertexFormat::Float32x4.size(),
|
|
||||||
format: wgpu::VertexFormat::Float32x3,
|
|
||||||
shader_location: 4,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -130,7 +140,18 @@ pub mod tile {
|
|||||||
include_str!("tile.fragment.wgsl"),
|
include_str!("tile.fragment.wgsl"),
|
||||||
&[wgpu::ColorTargetState {
|
&[wgpu::ColorTargetState {
|
||||||
format: COLOR_TEXTURE_FORMAT,
|
format: COLOR_TEXTURE_FORMAT,
|
||||||
blend: None,
|
blend: Some(wgpu::BlendState {
|
||||||
|
color: wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||||
|
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
alpha: wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||||
|
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
},
|
||||||
|
}),
|
||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
}],
|
}],
|
||||||
);
|
);
|
||||||
@ -281,18 +302,22 @@ impl ShaderTileMaskInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
|
||||||
|
pub struct ShaderFeatureStyle {
|
||||||
|
pub color: Vec4f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||||
pub struct ShaderTileMetadata {
|
pub struct ShaderTileMetadata {
|
||||||
pub color: Vec4f32,
|
|
||||||
pub translate: Vec3f32,
|
pub translate: Vec3f32,
|
||||||
_pad1: i32, // _padX aligns it to 16 bytes = AlignOf(Vec4f32/vec4<f32>): // https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size
|
_pad1: i32, // _padX aligns it to 16 bytes = AlignOf(Vec4f32/vec4<f32>): // https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShaderTileMetadata {
|
impl ShaderTileMetadata {
|
||||||
pub fn new(color: Vec4f32, translate: Vec3f32) -> Self {
|
pub fn new(translate: Vec3f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
color,
|
|
||||||
translate,
|
translate,
|
||||||
_pad1: Default::default(),
|
_pad1: Default::default(),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,8 +18,8 @@ struct VertexOutput {
|
|||||||
fn main(
|
fn main(
|
||||||
[[location(0)]] position: vec2<f32>,
|
[[location(0)]] position: vec2<f32>,
|
||||||
[[location(1)]] normal: vec2<f32>,
|
[[location(1)]] normal: vec2<f32>,
|
||||||
[[location(3)]] color: vec4<f32>,
|
|
||||||
[[location(4)]] translate: vec3<f32>,
|
[[location(4)]] translate: vec3<f32>,
|
||||||
|
[[location(5)]] color: vec4<f32>,
|
||||||
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
|
[[builtin(instance_index)]] instance_idx: u32 // instance_index is used when we have multiple instances of the same "object"
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
let z = 0.0;
|
let z = 0.0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user