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
|
||||
/// [here](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/custom_memory_pools.html).
|
||||
#[derive(Debug)]
|
||||
pub struct BufferPool<Q, B, V, I, M> {
|
||||
pub struct BufferPool<Q, B, V, I, M, FM> {
|
||||
vertices: BackingBuffer<B>,
|
||||
indices: BackingBuffer<B>,
|
||||
metadata: BackingBuffer<B>,
|
||||
feature_metadata: BackingBuffer<B>,
|
||||
|
||||
pub index: VecDeque<IndexEntry>,
|
||||
phantom_v: PhantomData<V>,
|
||||
phantom_i: PhantomData<I>,
|
||||
phantom_q: PhantomData<Q>,
|
||||
phantom_m: PhantomData<M>,
|
||||
phantom_fm: PhantomData<FM>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -40,15 +42,17 @@ enum BackingBufferType {
|
||||
VERTICES,
|
||||
INDICES,
|
||||
METADATA,
|
||||
FEATURE_METADATA,
|
||||
}
|
||||
|
||||
impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
||||
BufferPool<Q, B, V, I, M>
|
||||
impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod, FM: bytemuck::Pod>
|
||||
BufferPool<Q, B, V, I, M, FM>
|
||||
{
|
||||
pub fn new(
|
||||
vertices: BackingBufferDescriptor<B>,
|
||||
indices: BackingBufferDescriptor<B>,
|
||||
metadata: BackingBufferDescriptor<B>,
|
||||
feature_metadata: BackingBufferDescriptor<B>,
|
||||
) -> Self {
|
||||
Self {
|
||||
vertices: BackingBuffer::new(
|
||||
@ -66,11 +70,17 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
||||
metadata.inner_size,
|
||||
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
|
||||
phantom_v: Default::default(),
|
||||
phantom_i: Default::default(),
|
||||
phantom_q: 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::INDICES => &self.indices,
|
||||
BackingBufferType::METADATA => &self.metadata,
|
||||
BackingBufferType::FEATURE_METADATA => &self.feature_metadata,
|
||||
}
|
||||
.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
|
||||
}
|
||||
|
||||
pub fn feature_metadata(&self) -> &B {
|
||||
&self.feature_metadata.inner
|
||||
}
|
||||
|
||||
/// The VertexBuffers can contain padding elements. Not everything from a VertexBuffers is useable.
|
||||
/// The function returns the `bytes` and `aligned_bytes`. See [`OverAlignedVertexBuffer`].
|
||||
fn align(
|
||||
@ -121,14 +136,15 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
||||
pub fn allocate_geometry(
|
||||
&mut self,
|
||||
queue: &Q,
|
||||
id: u32,
|
||||
coords: TileCoords,
|
||||
over_aligned: &OverAlignedVertexBuffer<V, I>,
|
||||
metadata: M,
|
||||
feature_metadata: &Vec<FM>,
|
||||
) {
|
||||
let vertices_stride = size_of::<V>() as wgpu::BufferAddress;
|
||||
let indices_stride = size_of::<I>() 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(
|
||||
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,
|
||||
);
|
||||
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 {
|
||||
id,
|
||||
coords,
|
||||
buffer_vertices: self.vertices.make_room(vertices_bytes, &mut self.index),
|
||||
buffer_indices: self.indices.make_room(indices_bytes, &mut self.index),
|
||||
usable_indices: over_aligned.usable_indices as u32,
|
||||
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
|
||||
@ -168,6 +198,12 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, M: bytemuck::Pod>
|
||||
maybe_entry.buffer_metadata.start,
|
||||
&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);
|
||||
}
|
||||
|
||||
@ -235,11 +271,13 @@ impl<B> BackingBuffer<B> {
|
||||
BackingBufferType::VERTICES => first.buffer_vertices.start,
|
||||
BackingBufferType::INDICES => first.buffer_indices.start,
|
||||
BackingBufferType::METADATA => first.buffer_metadata.start,
|
||||
BackingBufferType::FEATURE_METADATA => 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_metadata.end,
|
||||
BackingBufferType::FEATURE_METADATA => first.buffer_feature_metadata.end,
|
||||
});
|
||||
|
||||
if let Some(start) = start {
|
||||
@ -272,7 +310,6 @@ impl<B> BackingBuffer<B> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IndexEntry {
|
||||
pub id: u32,
|
||||
pub coords: TileCoords,
|
||||
// Range of bytes within the backing buffer for vertices
|
||||
buffer_vertices: Range<wgpu::BufferAddress>,
|
||||
@ -280,6 +317,8 @@ pub struct IndexEntry {
|
||||
buffer_indices: Range<wgpu::BufferAddress>,
|
||||
// Range of bytes within the backing buffer for metadata
|
||||
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`.
|
||||
// Can be lower than size(buffer_indices) / indices_stride because of alignment.
|
||||
usable_indices: u32,
|
||||
@ -301,6 +340,10 @@ impl IndexEntry {
|
||||
pub fn metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||
self.buffer_metadata.clone()
|
||||
}
|
||||
|
||||
pub fn feature_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||
self.buffer_feature_metadata.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use std::cmp;
|
||||
use std::default::Default;
|
||||
use std::{cmp, iter};
|
||||
|
||||
use log::trace;
|
||||
use vector_tile::tile::Layer;
|
||||
use wgpu::{Buffer, BufferAddress, Limits, Queue};
|
||||
use winit::dpi::PhysicalSize;
|
||||
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::render::buffer_pool::{BackingBufferDescriptor, BufferPool};
|
||||
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::tesselation::IndexDataType;
|
||||
use crate::util::FPSMeter;
|
||||
@ -19,12 +24,6 @@ use super::shaders;
|
||||
use super::shaders::*;
|
||||
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 {
|
||||
instance: wgpu::Instance,
|
||||
|
||||
@ -50,7 +49,14 @@ pub struct RenderState {
|
||||
|
||||
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_instances_buffer: wgpu::Buffer,
|
||||
@ -103,11 +109,17 @@ impl RenderState {
|
||||
};
|
||||
|
||||
// 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
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
features: wgpu::Features::default(),
|
||||
features,
|
||||
limits,
|
||||
},
|
||||
None,
|
||||
@ -115,26 +127,33 @@ impl RenderState {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let vertex_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: VERTEX_BUFFER_SIZE,
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
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,
|
||||
size: INDICES_BUFFER_SIZE,
|
||||
usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
|
||||
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;
|
||||
|
||||
let tile_mask_instances = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: tile_masks_uniform_buffer_size,
|
||||
size: tile_masks_instances_buffer_size,
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
@ -142,11 +161,11 @@ impl RenderState {
|
||||
let globals_buffer_byte_size =
|
||||
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;
|
||||
let tiles_uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
let metadata_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Tiles ubo"),
|
||||
size: tiles_uniform_buffer_size,
|
||||
size: metadata_buffer_size,
|
||||
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
@ -273,9 +292,10 @@ impl RenderState {
|
||||
perspective: projection,
|
||||
suspended: false, // Initially the app is not suspended
|
||||
buffer_pool: BufferPool::new(
|
||||
BackingBufferDescriptor::new(vertex_uniform_buffer, VERTEX_BUFFER_SIZE),
|
||||
BackingBufferDescriptor::new(indices_uniform_buffer, INDICES_BUFFER_SIZE),
|
||||
BackingBufferDescriptor::new(tiles_uniform_buffer, tiles_uniform_buffer_size),
|
||||
BackingBufferDescriptor::new(vertex_buffer, VERTEX_BUFFER_SIZE),
|
||||
BackingBufferDescriptor::new(indices_buffer, INDICES_BUFFER_SIZE),
|
||||
BackingBufferDescriptor::new(metadata_buffer, metadata_buffer_size),
|
||||
BackingBufferDescriptor::new(feature_metadata_buffer, FEATURE_METADATA_BUFFER_SIZE),
|
||||
),
|
||||
tile_mask_pattern: TileMaskPattern::new(),
|
||||
}
|
||||
@ -332,19 +352,47 @@ impl RenderState {
|
||||
pub fn upload_tile_geometry(&mut self, worker_loop: &WorkerLoop) {
|
||||
let upload = worker_loop.pop_all();
|
||||
|
||||
for tile in upload.iter() {
|
||||
let world_coords = tile.coords.into_world_tile();
|
||||
for layer in upload.iter() {
|
||||
let world_coords = layer.coords.into_world_tile();
|
||||
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.queue,
|
||||
tile.id,
|
||||
tile.coords,
|
||||
&tile.over_aligned,
|
||||
ShaderTileMetadata::new(
|
||||
[0.0, 0.0, 0.0, 1.0],
|
||||
world_coords.into_world(4096.0).into(),
|
||||
),
|
||||
layer.coords,
|
||||
&layer.buffer,
|
||||
ShaderTileMetadata::new(world_coords.into_world(4096.0).into()),
|
||||
&feature_metadata,
|
||||
);
|
||||
}
|
||||
|
||||
@ -442,18 +490,18 @@ impl RenderState {
|
||||
.vertices()
|
||||
.slice(entry.vertices_buffer_range()),
|
||||
);
|
||||
let id = entry.id as BufferAddress;
|
||||
pass.set_vertex_buffer(
|
||||
1,
|
||||
self.buffer_pool
|
||||
.metadata()
|
||||
.slice(entry.metadata_buffer_range()),
|
||||
);
|
||||
/* if !self.tile_fill_range.is_empty() {
|
||||
pass.draw_indexed(self.tile_fill_range.clone(), 0, 0..1);
|
||||
}*/
|
||||
trace!("current buffer_pool index {:?}", self.buffer_pool.index);
|
||||
// FIXME: Custom Instance index possibly breaks on Metal
|
||||
pass.set_vertex_buffer(
|
||||
2,
|
||||
self.buffer_pool
|
||||
.feature_metadata()
|
||||
.slice(entry.feature_metadata_buffer_range()),
|
||||
);
|
||||
pass.draw_indexed(entry.indices_range(), 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,12 +81,14 @@ impl VertexShaderState {
|
||||
pub mod tile {
|
||||
use super::{ShaderTileMetadata, ShaderVertex};
|
||||
use crate::platform::COLOR_TEXTURE_FORMAT;
|
||||
use wgpu::BlendState;
|
||||
|
||||
use super::{FragmentShaderState, VertexShaderState};
|
||||
|
||||
pub const VERTEX: VertexShaderState = VertexShaderState::new(
|
||||
include_str!("tile.vertex.wgsl"),
|
||||
&[
|
||||
// vertex data
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ShaderVertex>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
@ -105,21 +107,29 @@ pub mod tile {
|
||||
},
|
||||
],
|
||||
},
|
||||
// tile metadata
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
||||
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: &[
|
||||
// color
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
format: wgpu::VertexFormat::Float32x4,
|
||||
shader_location: 3,
|
||||
},
|
||||
// translate
|
||||
wgpu::VertexAttribute {
|
||||
offset: wgpu::VertexFormat::Float32x4.size(),
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
shader_location: 4,
|
||||
shader_location: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -130,7 +140,18 @@ pub mod tile {
|
||||
include_str!("tile.fragment.wgsl"),
|
||||
&[wgpu::ColorTargetState {
|
||||
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,
|
||||
}],
|
||||
);
|
||||
@ -281,18 +302,22 @@ impl ShaderTileMaskInstance {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
|
||||
pub struct ShaderFeatureStyle {
|
||||
pub color: Vec4f32,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
pub fn new(translate: Vec3f32) -> Self {
|
||||
Self {
|
||||
color,
|
||||
translate,
|
||||
_pad1: Default::default(),
|
||||
}
|
||||
|
||||
@ -18,8 +18,8 @@ struct VertexOutput {
|
||||
fn main(
|
||||
[[location(0)]] position: vec2<f32>,
|
||||
[[location(1)]] normal: vec2<f32>,
|
||||
[[location(3)]] color: vec4<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"
|
||||
) -> VertexOutput {
|
||||
let z = 0.0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user