mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Improve headless feature structure (#128)
* Collect headless related stuff under feature flag * Run clippy
This commit is contained in:
parent
4a57d052d8
commit
1c46a77ce0
@ -6,7 +6,7 @@ use maplibre::platform::run_multithreaded;
|
||||
use maplibre::platform::schedule_method::TokioScheduleMethod;
|
||||
use maplibre::render::settings::{Backends, WgpuSettings};
|
||||
use maplibre::MapBuilder;
|
||||
use maplibre_winit::winit::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow};
|
||||
use maplibre_winit::winit::WinitMapWindowConfig;
|
||||
use std::ffi::CString;
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
@ -33,7 +33,10 @@ pub fn android_main() {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_org_maplibre_1rs_MapLibreRs_android_1main(env: JNIEnv, class: JClass) {
|
||||
pub extern "system" fn Java_org_maplibre_1rs_MapLibreRs_android_1main(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
) {
|
||||
let tag = CString::new("maplibre").unwrap();
|
||||
let message = CString::new("maplibre WOORKING").unwrap();
|
||||
ndk_glue::android_log(Level::Warn, &tag, &message);
|
||||
|
||||
12
justfile
12
justfile
@ -14,6 +14,18 @@ install-clippy:
|
||||
install-nightly-clippy:
|
||||
rustup component add clippy --toolchain $NIGHTLY_TOOLCHAIN
|
||||
|
||||
fixup:
|
||||
cargo clippy --no-deps -p maplibre --fix
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre-winit --fix
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre-demo --fix
|
||||
# Web
|
||||
cargo clippy --allow-dirty --no-deps -p web --target wasm32-unknown-unknown --fix
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre --target wasm32-unknown-unknown --fix
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre-winit --target wasm32-unknown-unknown --fix
|
||||
# Android
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre-winit --target x86_64-linux-android --fix
|
||||
cargo clippy --allow-dirty --no-deps -p maplibre-android --target x86_64-linux-android --fix
|
||||
|
||||
check PROJECT ARCH: install-clippy
|
||||
cargo clippy --no-deps -p {{PROJECT}} --target {{ARCH}}
|
||||
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
use maplibre::benchmarking::tessellation::{IndexDataType, OverAlignedVertexBuffer};
|
||||
use maplibre::coords::{WorldTileCoords, ZoomLevel};
|
||||
use maplibre::error::Error;
|
||||
use maplibre::headless::HeadlessMapWindowConfig;
|
||||
use maplibre::io::pipeline::Processable;
|
||||
use maplibre::io::pipeline::{PipelineContext, PipelineProcessor};
|
||||
use maplibre::io::scheduler::ScheduleMethod;
|
||||
|
||||
use maplibre::io::source_client::{HttpClient, HttpSourceClient};
|
||||
use maplibre::io::tile_pipelines::build_vector_tile_pipeline;
|
||||
use maplibre::io::tile_repository::StoredLayer;
|
||||
use maplibre::io::{RawLayer, TileRequest, TileRequestID};
|
||||
use maplibre::map_schedule::{EventuallyMapContext, InteractiveMapSchedule};
|
||||
use maplibre::io::{RawLayer, TileRequest};
|
||||
|
||||
use maplibre::platform::http_client::ReqwestHttpClient;
|
||||
use maplibre::platform::run_multithreaded;
|
||||
use maplibre::platform::schedule_method::TokioScheduleMethod;
|
||||
use maplibre::render::settings::{RendererSettings, TextureFormat};
|
||||
use maplibre::render::ShaderVertex;
|
||||
use maplibre::window::{EventLoop, MapWindow, MapWindowConfig, WindowSize};
|
||||
use maplibre::window::{EventLoop, WindowSize};
|
||||
use maplibre::MapBuilder;
|
||||
use maplibre_winit::winit::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow};
|
||||
use std::any::Any;
|
||||
use maplibre_winit::winit::WinitMapWindowConfig;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
@ -29,27 +30,6 @@ fn enable_tracing() {
|
||||
|
||||
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
|
||||
}
|
||||
pub struct HeadlessMapWindowConfig {
|
||||
size: WindowSize,
|
||||
}
|
||||
|
||||
impl MapWindowConfig for HeadlessMapWindowConfig {
|
||||
type MapWindow = HeadlessMapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
Self::MapWindow { size: self.size }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeadlessMapWindow {
|
||||
size: WindowSize,
|
||||
}
|
||||
|
||||
impl MapWindow for HeadlessMapWindow {
|
||||
fn size(&self) -> WindowSize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
fn run_in_window() {
|
||||
run_multithreaded(async {
|
||||
@ -157,6 +137,6 @@ fn main() {
|
||||
#[cfg(feature = "trace")]
|
||||
enable_tracing();
|
||||
|
||||
//run_headless();
|
||||
run_headless();
|
||||
run_in_window();
|
||||
}
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
use crate::input::{InputController, UpdateState};
|
||||
use instant::Instant;
|
||||
use maplibre::error::Error;
|
||||
use maplibre::io::scheduler::ScheduleMethod;
|
||||
use maplibre::io::source_client::HttpClient;
|
||||
use std::borrow::BorrowMut;
|
||||
use maplibre::map_schedule::InteractiveMapSchedule;
|
||||
use maplibre::window::{EventLoop, HeadedMapWindow, MapWindowConfig};
|
||||
use winit::event::Event;
|
||||
use winit::event::{ElementState, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||
use winit::event_loop::ControlFlow;
|
||||
|
||||
use crate::input::{InputController, UpdateState};
|
||||
use maplibre::map_schedule::InteractiveMapSchedule;
|
||||
use maplibre::window::{EventLoop, HeadedMapWindow, MapWindow, MapWindowConfig};
|
||||
use winit::event::Event;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod web;
|
||||
|
||||
@ -89,7 +87,7 @@ where
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task;
|
||||
|
||||
let state = task::block_in_place(|| {
|
||||
task::block_in_place(|| {
|
||||
Handle::current().block_on(async {
|
||||
map_schedule.late_init().await;
|
||||
})
|
||||
|
||||
@ -3,9 +3,6 @@
|
||||
//! This script is built and executed just before building the package.
|
||||
//! It will validate the WGSL (WebGPU Shading Language) shaders and embed static files.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{env, fs};
|
||||
|
||||
#[cfg(feature = "embed-static-tiles")]
|
||||
use maplibre_build_tools::mbtiles::extract;
|
||||
use maplibre_build_tools::wgsl::validate_project_wgsl;
|
||||
@ -16,13 +13,13 @@ const MUNICH_Z: u8 = 15;
|
||||
|
||||
/// Tiles which can be used by StaticTileFetcher.
|
||||
#[cfg(feature = "embed-static-tiles")]
|
||||
fn clean_static_tiles() -> PathBuf {
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
fn clean_static_tiles() -> std::path::PathBuf {
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
|
||||
let out = Path::new(&out_dir).join("extracted-tiles");
|
||||
let out = std::path::Path::new(&out_dir).join("extracted-tiles");
|
||||
|
||||
if out.exists() && out.is_dir() {
|
||||
fs::remove_dir_all(&out).unwrap()
|
||||
std::fs::remove_dir_all(&out).unwrap()
|
||||
}
|
||||
|
||||
out
|
||||
@ -52,6 +49,8 @@ fn generate_type_def() -> Option<u32> {
|
||||
|
||||
#[cfg(feature = "embed-static-tiles")]
|
||||
fn embed_tiles_statically() {
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
let out = clean_static_tiles();
|
||||
|
||||
let root_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
@ -2,8 +2,7 @@ use crate::coords::{Zoom, ZoomLevel, TILE_SIZE};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::{Camera, Perspective, ViewProjection};
|
||||
use crate::util::ChangeObserver;
|
||||
use crate::{Renderer, ScheduleMethod, Style, WindowSize};
|
||||
use std::sync::mpsc;
|
||||
use crate::{Renderer, Style, WindowSize};
|
||||
|
||||
/// Stores the camera configuration.
|
||||
pub struct ViewState {
|
||||
|
||||
@ -63,7 +63,7 @@ pub struct ZoomLevel(u8);
|
||||
|
||||
impl ZoomLevel {
|
||||
pub fn is_root(self) -> bool {
|
||||
return self.0 == 0;
|
||||
self.0 == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
244
maplibre/src/headless.rs
Normal file
244
maplibre/src/headless.rs
Normal file
@ -0,0 +1,244 @@
|
||||
use crate::context::{MapContext, ViewState};
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::error::Error;
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::ViewProjection;
|
||||
use crate::render::graph::{Node, NodeRunError, RenderContext, RenderGraphContext, SlotInfo};
|
||||
use crate::render::resource::{BufferDimensions, BufferedTextureHead, IndexEntry};
|
||||
use crate::render::resource::{Head, TrackedRenderPass};
|
||||
use crate::render::stages::RenderStageLabel;
|
||||
use crate::render::{
|
||||
create_default_render_graph, draw_graph, register_default_render_stages, RenderState,
|
||||
};
|
||||
use crate::schedule::{Schedule, Stage};
|
||||
use crate::{
|
||||
HttpClient, MapWindow, MapWindowConfig, Renderer, ScheduleMethod, Scheduler, Style, WindowSize,
|
||||
};
|
||||
use std::fs::File;
|
||||
use std::future::Future;
|
||||
use std::io::Write;
|
||||
use std::iter;
|
||||
use std::ops::{Deref, Range};
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task;
|
||||
use wgpu::{BufferAsyncError, BufferSlice};
|
||||
|
||||
pub struct HeadlessMapWindowConfig {
|
||||
pub size: WindowSize,
|
||||
}
|
||||
|
||||
impl MapWindowConfig for HeadlessMapWindowConfig {
|
||||
type MapWindow = HeadlessMapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
Self::MapWindow { size: self.size }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeadlessMapWindow {
|
||||
size: WindowSize,
|
||||
}
|
||||
|
||||
impl MapWindow for HeadlessMapWindow {
|
||||
fn size(&self) -> WindowSize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeadlessMap<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
pub map_schedule: HeadlessMapSchedule<MWC, SM, HC>,
|
||||
pub window: MWC::MapWindow,
|
||||
}
|
||||
|
||||
impl<MWC, SM, HC> HeadlessMap<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
pub fn map_schedule_mut(&mut self) -> &mut HeadlessMapSchedule<MWC, SM, HC> {
|
||||
&mut self.map_schedule
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the state of the map, dispatches tile fetching and caching, tessellation and drawing.
|
||||
pub struct HeadlessMapSchedule<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
map_window_config: MWC,
|
||||
|
||||
pub map_context: MapContext,
|
||||
|
||||
schedule: Schedule,
|
||||
scheduler: Scheduler<SM>,
|
||||
http_client: HC,
|
||||
}
|
||||
|
||||
impl<MWC, SM, HC> HeadlessMapSchedule<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
pub fn new(
|
||||
map_window_config: MWC,
|
||||
window_size: WindowSize,
|
||||
renderer: Renderer,
|
||||
scheduler: Scheduler<SM>,
|
||||
http_client: HC,
|
||||
style: Style,
|
||||
) -> Self {
|
||||
let view_state = ViewState::new(&window_size);
|
||||
let tile_repository = TileRepository::new();
|
||||
let mut schedule = Schedule::default();
|
||||
|
||||
let mut graph = create_default_render_graph().unwrap();
|
||||
let draw_graph = graph.get_sub_graph_mut(draw_graph::NAME).unwrap();
|
||||
draw_graph.add_node(draw_graph::node::COPY, CopySurfaceBufferNode::default());
|
||||
draw_graph
|
||||
.add_node_edge(draw_graph::node::MAIN_PASS, draw_graph::node::COPY)
|
||||
.unwrap();
|
||||
|
||||
register_default_render_stages(graph, &mut schedule);
|
||||
|
||||
schedule.add_stage(
|
||||
RenderStageLabel::Cleanup,
|
||||
WriteSurfaceBufferStage::default(),
|
||||
);
|
||||
|
||||
Self {
|
||||
map_window_config,
|
||||
map_context: MapContext {
|
||||
view_state,
|
||||
style,
|
||||
tile_repository,
|
||||
renderer,
|
||||
},
|
||||
schedule,
|
||||
scheduler,
|
||||
http_client,
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "update_and_redraw", skip_all)]
|
||||
pub fn update_and_redraw(&mut self) -> Result<(), Error> {
|
||||
self.schedule.run(&mut self.map_context);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn schedule(&self) -> &Schedule {
|
||||
&self.schedule
|
||||
}
|
||||
pub fn scheduler(&self) -> &Scheduler<SM> {
|
||||
&self.scheduler
|
||||
}
|
||||
pub fn http_client(&self) -> &HC {
|
||||
&self.http_client
|
||||
}
|
||||
}
|
||||
|
||||
/// Node which copies the contents of the GPU-side texture in [`BufferedTextureHead`] to an
|
||||
/// unmapped GPU-side buffer. This buffer will be mapped in
|
||||
/// [`crate::render::stages::write_surface_buffer_stage::WriteSurfaceBufferStage`].
|
||||
#[derive(Default)]
|
||||
pub struct CopySurfaceBufferNode {}
|
||||
|
||||
impl CopySurfaceBufferNode {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for CopySurfaceBufferNode {
|
||||
fn input(&self) -> Vec<SlotInfo> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn update(&mut self, _state: &mut RenderState) {}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
RenderContext {
|
||||
command_encoder, ..
|
||||
}: &mut RenderContext,
|
||||
state: &RenderState,
|
||||
) -> Result<(), NodeRunError> {
|
||||
match state.surface.head() {
|
||||
Head::Headed(_) => {}
|
||||
Head::Headless(buffered_texture) => {
|
||||
let size = state.surface.size();
|
||||
command_encoder.copy_texture_to_buffer(
|
||||
buffered_texture.texture.as_image_copy(),
|
||||
wgpu::ImageCopyBuffer {
|
||||
buffer: &buffered_texture.output_buffer,
|
||||
layout: wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(
|
||||
std::num::NonZeroU32::new(
|
||||
buffered_texture.buffer_dimensions.padded_bytes_per_row as u32,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
rows_per_image: None,
|
||||
},
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: size.width() as u32,
|
||||
height: size.height() as u32,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Stage which writes the current contents of the GPU/CPU buffer in [`BufferedTextureHead`]
|
||||
/// to disk as PNG.
|
||||
#[derive(Default)]
|
||||
pub struct WriteSurfaceBufferStage {
|
||||
frame: u64,
|
||||
}
|
||||
|
||||
impl Stage for WriteSurfaceBufferStage {
|
||||
fn run(
|
||||
&mut self,
|
||||
MapContext {
|
||||
renderer: Renderer { state, device, .. },
|
||||
..
|
||||
}: &mut MapContext,
|
||||
) {
|
||||
match state.surface.head() {
|
||||
Head::Headed(_) => {}
|
||||
Head::Headless(buffered_texture) => {
|
||||
let buffered_texture: Arc<BufferedTextureHead> = buffered_texture.clone();
|
||||
|
||||
let device = device.clone();
|
||||
let current_frame = self.frame;
|
||||
|
||||
task::block_in_place(|| {
|
||||
Handle::current().block_on(async {
|
||||
buffered_texture
|
||||
.create_png(&device, format!("frame_{}.png", current_frame).as_str())
|
||||
.await;
|
||||
})
|
||||
});
|
||||
|
||||
self.frame += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
//! Handles IO related processing as well as multithreading.
|
||||
|
||||
use crate::coords::WorldTileCoords;
|
||||
use crate::render::ShaderVertex;
|
||||
use crate::tessellation::{IndexDataType, OverAlignedVertexBuffer};
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
pub mod scheduler;
|
||||
|
||||
@ -5,27 +5,25 @@ use crate::render::ShaderVertex;
|
||||
use crate::tessellation::{IndexDataType, OverAlignedVertexBuffer};
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use geozero::mvt::tile;
|
||||
use std::any::Any;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::process::Output;
|
||||
use std::sync::mpsc;
|
||||
|
||||
/// Processes events which happen during the pipeline execution
|
||||
pub trait PipelineProcessor: Downcast {
|
||||
fn tile_finished(&mut self, request_id: TileRequestID, coords: &WorldTileCoords) {}
|
||||
fn layer_unavailable(&mut self, coords: &WorldTileCoords, layer_name: &str) {}
|
||||
fn tile_finished(&mut self, _request_id: TileRequestID, _coords: &WorldTileCoords) {}
|
||||
fn layer_unavailable(&mut self, _coords: &WorldTileCoords, _layer_name: &str) {}
|
||||
fn layer_tesselation_finished(
|
||||
&mut self,
|
||||
coords: &WorldTileCoords,
|
||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
feature_indices: Vec<u32>,
|
||||
layer_data: tile::Layer,
|
||||
_coords: &WorldTileCoords,
|
||||
_buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
_feature_indices: Vec<u32>,
|
||||
_layer_data: tile::Layer,
|
||||
) {
|
||||
}
|
||||
fn layer_indexing_finished(
|
||||
&mut self,
|
||||
coords: &WorldTileCoords,
|
||||
geometries: Vec<IndexedGeometry<f64>>,
|
||||
_coords: &WorldTileCoords,
|
||||
_geometries: Vec<IndexedGeometry<f64>>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
@ -181,17 +179,16 @@ mod tests {
|
||||
ClosureProcessable, DataPipeline, PipelineContext, PipelineEnd, PipelineProcessor,
|
||||
Processable,
|
||||
};
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub struct DummyPipelineProcessor;
|
||||
|
||||
impl PipelineProcessor for DummyPipelineProcessor {}
|
||||
|
||||
fn add_one(input: u32, context: &mut PipelineContext) -> u8 {
|
||||
fn add_one(input: u32, _context: &mut PipelineContext) -> u8 {
|
||||
input as u8 + 1
|
||||
}
|
||||
|
||||
fn add_two(input: u8, context: &mut PipelineContext) -> u32 {
|
||||
fn add_two(input: u8, _context: &mut PipelineContext) -> u32 {
|
||||
input as u32 + 2
|
||||
}
|
||||
|
||||
@ -219,22 +216,21 @@ mod tests {
|
||||
#[test]
|
||||
fn test_closure() {
|
||||
let mut context = PipelineContext::new(DummyPipelineProcessor);
|
||||
let mut outer_value = 3;
|
||||
let outer_value = 3;
|
||||
|
||||
// using from()
|
||||
let closure = ClosureProcessable::from(|input: u8, context: &mut PipelineContext| -> u32 {
|
||||
return input as u32 + 2 + outer_value;
|
||||
});
|
||||
let closure =
|
||||
ClosureProcessable::from(|input: u8, _context: &mut PipelineContext| -> u32 {
|
||||
input as u32 + 2 + outer_value
|
||||
});
|
||||
let output: u32 =
|
||||
DataPipeline::new(closure, PipelineEnd::default()).process(5u8, &mut context);
|
||||
assert_eq!(output, 10);
|
||||
|
||||
// with into()
|
||||
let output: u32 = DataPipeline::<ClosureProcessable<_, u8, u32>, _>::new(
|
||||
(|input: u8, context: &mut PipelineContext| -> u32 {
|
||||
return input as u32 + 2 + outer_value;
|
||||
})
|
||||
.into(),
|
||||
(|input: u8, _context: &mut PipelineContext| -> u32 { input as u32 + 2 + outer_value })
|
||||
.into(),
|
||||
PipelineEnd::<u32>::default(),
|
||||
)
|
||||
.process(5u8, &mut context);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
//! Scheduling.
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
|
||||
@ -55,11 +55,6 @@ impl StaticTileFetcher {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::style::source::TileAddressingScheme;
|
||||
|
||||
use crate::coords::WorldTileCoords;
|
||||
|
||||
use super::StaticTileFetcher;
|
||||
|
||||
#[cfg(all(static_tiles, not(target_arch = "wasm32")))]
|
||||
#[tokio::test]
|
||||
|
||||
@ -141,7 +141,7 @@ mod tests {
|
||||
let mut context = PipelineContext::new(DummyPipelineProcessor);
|
||||
|
||||
let pipeline = build_vector_tile_pipeline();
|
||||
let output = pipeline.process(
|
||||
let _output = pipeline.process(
|
||||
(
|
||||
TileRequest {
|
||||
coords: (0, 0, ZoomLevel::default()).into(),
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
use crate::io::scheduler::{ScheduleMethod, Scheduler};
|
||||
use crate::io::source_client::HttpClient;
|
||||
use crate::map_schedule::{InteractiveMapSchedule, SimpleMapSchedule};
|
||||
use crate::map_schedule::InteractiveMapSchedule;
|
||||
use crate::render::settings::{RendererSettings, WgpuSettings};
|
||||
use crate::render::{RenderState, Renderer};
|
||||
use crate::style::Style;
|
||||
@ -27,6 +27,8 @@ use crate::window::{EventLoop, HeadedMapWindow, MapWindow, MapWindowConfig, Wind
|
||||
pub mod context;
|
||||
pub mod coords;
|
||||
pub mod error;
|
||||
#[cfg(feature = "headless")]
|
||||
pub mod headless;
|
||||
pub mod io;
|
||||
// Exposed because of input handlers in maplibre-winit
|
||||
pub mod map_schedule;
|
||||
@ -34,6 +36,7 @@ pub mod platform;
|
||||
// Exposed because of camera
|
||||
pub mod render;
|
||||
pub mod style;
|
||||
|
||||
pub mod window;
|
||||
// Exposed because of doc-strings
|
||||
pub mod schedule;
|
||||
@ -106,27 +109,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HeadlessMap<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
map_schedule: SimpleMapSchedule<MWC, SM, HC>,
|
||||
window: MWC::MapWindow,
|
||||
}
|
||||
|
||||
impl<MWC, SM, HC> HeadlessMap<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
pub fn map_schedule_mut(&mut self) -> &mut SimpleMapSchedule<MWC, SM, HC> {
|
||||
&mut self.map_schedule
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the map configuration before the map's state has been fully initialized.
|
||||
pub struct UninitializedMap<MWC, SM, HC>
|
||||
where
|
||||
@ -184,7 +166,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn initialize_headless(self) -> HeadlessMap<MWC, SM, HC> {
|
||||
#[cfg(feature = "headless")]
|
||||
pub async fn initialize_headless(self) -> headless::HeadlessMap<MWC, SM, HC> {
|
||||
let window = self.map_window_config.create();
|
||||
let window_size = window.size();
|
||||
|
||||
@ -195,8 +178,8 @@ where
|
||||
)
|
||||
.await
|
||||
.expect("Failed to initialize renderer");
|
||||
HeadlessMap {
|
||||
map_schedule: SimpleMapSchedule::new(
|
||||
headless::HeadlessMap {
|
||||
map_schedule: headless::HeadlessMapSchedule::new(
|
||||
self.map_window_config,
|
||||
window_size,
|
||||
renderer,
|
||||
|
||||
@ -1,61 +1,20 @@
|
||||
use crate::context::{MapContext, ViewState};
|
||||
use crate::error::Error;
|
||||
use crate::io::geometry_index::GeometryIndex;
|
||||
|
||||
use crate::io::scheduler::Scheduler;
|
||||
use crate::io::source_client::{HttpClient, HttpSourceClient, SourceClient};
|
||||
use crate::io::source_client::{HttpClient, HttpSourceClient};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::io::tile_request_state::TileRequestState;
|
||||
use crate::render::register_render_stages;
|
||||
|
||||
use crate::render::{create_default_render_graph, register_default_render_stages};
|
||||
use crate::schedule::{Schedule, Stage};
|
||||
use crate::stages::register_stages;
|
||||
use crate::style::Style;
|
||||
use crate::{
|
||||
HeadedMapWindow, MapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod,
|
||||
WgpuSettings, WindowSize,
|
||||
HeadedMapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod, WgpuSettings,
|
||||
WindowSize,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
|
||||
pub struct PrematureMapContext {
|
||||
view_state: ViewState,
|
||||
style: Style,
|
||||
|
||||
tile_repository: TileRepository,
|
||||
|
||||
wgpu_settings: WgpuSettings,
|
||||
renderer_settings: RendererSettings,
|
||||
}
|
||||
|
||||
pub enum EventuallyMapContext {
|
||||
Full(MapContext),
|
||||
Premature(PrematureMapContext),
|
||||
_Uninitialized,
|
||||
}
|
||||
|
||||
impl EventuallyMapContext {
|
||||
pub fn make_full(&mut self, renderer: Renderer) {
|
||||
let context = mem::replace(self, EventuallyMapContext::_Uninitialized);
|
||||
|
||||
match context {
|
||||
EventuallyMapContext::Full(_) => {}
|
||||
EventuallyMapContext::Premature(PrematureMapContext {
|
||||
view_state,
|
||||
style,
|
||||
tile_repository,
|
||||
..
|
||||
}) => {
|
||||
*self = EventuallyMapContext::Full(MapContext {
|
||||
view_state,
|
||||
style,
|
||||
tile_repository,
|
||||
renderer,
|
||||
});
|
||||
}
|
||||
EventuallyMapContext::_Uninitialized => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the state of the map, dispatches tile fetching and caching, tessellation and drawing.
|
||||
pub struct InteractiveMapSchedule<MWC, SM, HC>
|
||||
@ -66,7 +25,7 @@ where
|
||||
{
|
||||
map_window_config: MWC,
|
||||
|
||||
pub map_context: EventuallyMapContext,
|
||||
map_context: EventuallyMapContext,
|
||||
|
||||
schedule: Schedule,
|
||||
|
||||
@ -99,7 +58,8 @@ where
|
||||
let http_source_client: HttpSourceClient<HC> = HttpSourceClient::new(http_client);
|
||||
register_stages(&mut schedule, http_source_client, Box::new(scheduler));
|
||||
|
||||
register_render_stages(&mut schedule, false).unwrap();
|
||||
let graph = create_default_render_graph().unwrap();
|
||||
register_default_render_stages(graph, &mut schedule);
|
||||
|
||||
Self {
|
||||
map_window_config,
|
||||
@ -157,7 +117,7 @@ where
|
||||
<MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
|
||||
{
|
||||
if let EventuallyMapContext::Full(map_context) = &mut self.map_context {
|
||||
let mut renderer = &mut map_context.renderer;
|
||||
let renderer = &mut map_context.renderer;
|
||||
renderer
|
||||
.state
|
||||
.recreate_surface::<MWC::MapWindow>(window, &renderer.instance);
|
||||
@ -204,70 +164,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the state of the map, dispatches tile fetching and caching, tessellation and drawing.
|
||||
pub struct SimpleMapSchedule<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
map_window_config: MWC,
|
||||
pub struct PrematureMapContext {
|
||||
view_state: ViewState,
|
||||
style: Style,
|
||||
|
||||
pub map_context: MapContext,
|
||||
tile_repository: TileRepository,
|
||||
|
||||
schedule: Schedule,
|
||||
scheduler: Scheduler<SM>,
|
||||
http_client: HC,
|
||||
wgpu_settings: WgpuSettings,
|
||||
renderer_settings: RendererSettings,
|
||||
}
|
||||
|
||||
impl<MWC, SM, HC> SimpleMapSchedule<MWC, SM, HC>
|
||||
where
|
||||
MWC: MapWindowConfig,
|
||||
SM: ScheduleMethod,
|
||||
HC: HttpClient,
|
||||
{
|
||||
pub fn new(
|
||||
map_window_config: MWC,
|
||||
window_size: WindowSize,
|
||||
renderer: Renderer,
|
||||
scheduler: Scheduler<SM>,
|
||||
http_client: HC,
|
||||
style: Style,
|
||||
) -> Self {
|
||||
let view_state = ViewState::new(&window_size);
|
||||
let tile_repository = TileRepository::new();
|
||||
let mut schedule = Schedule::default();
|
||||
pub enum EventuallyMapContext {
|
||||
Full(MapContext),
|
||||
Premature(PrematureMapContext),
|
||||
_Uninitialized,
|
||||
}
|
||||
|
||||
register_render_stages(&mut schedule, true).unwrap();
|
||||
impl EventuallyMapContext {
|
||||
pub fn make_full(&mut self, renderer: Renderer) {
|
||||
let context = mem::replace(self, EventuallyMapContext::_Uninitialized);
|
||||
|
||||
Self {
|
||||
map_window_config,
|
||||
map_context: MapContext {
|
||||
match context {
|
||||
EventuallyMapContext::Full(_) => {}
|
||||
EventuallyMapContext::Premature(PrematureMapContext {
|
||||
view_state,
|
||||
style,
|
||||
tile_repository,
|
||||
renderer,
|
||||
},
|
||||
schedule,
|
||||
scheduler,
|
||||
http_client,
|
||||
..
|
||||
}) => {
|
||||
*self = EventuallyMapContext::Full(MapContext {
|
||||
view_state,
|
||||
style,
|
||||
tile_repository,
|
||||
renderer,
|
||||
});
|
||||
}
|
||||
EventuallyMapContext::_Uninitialized => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(name = "update_and_redraw", skip_all)]
|
||||
pub fn update_and_redraw(&mut self) -> Result<(), Error> {
|
||||
self.schedule.run(&mut self.map_context);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn schedule(&self) -> &Schedule {
|
||||
&self.schedule
|
||||
}
|
||||
pub fn scheduler(&self) -> &Scheduler<SM> {
|
||||
&self.scheduler
|
||||
}
|
||||
pub fn http_client(&self) -> &HC {
|
||||
&self.http_client
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::error::Error;
|
||||
use crate::ScheduleMethod;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Multi-threading with Tokio.
|
||||
pub struct TokioScheduleMethod;
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
//! Node which copies the contents of the GPU-side texture in [`BufferedTextureHead`] to an
|
||||
//! unmapped GPU-side buffer. This buffer will be mapped in
|
||||
//! [`crate::render::stages::write_surface_buffer_stage::WriteSurfaceBufferStage`].
|
||||
|
||||
use crate::render::graph::{Node, NodeRunError, RenderContext, RenderGraphContext, SlotInfo};
|
||||
use crate::render::render_commands::{DrawMasks, DrawTiles};
|
||||
use crate::render::render_phase::{PhaseItem, RenderCommand};
|
||||
use crate::render::resource::{Head, TrackedRenderPass};
|
||||
use crate::render::util::FloatOrd;
|
||||
use crate::render::Eventually::Initialized;
|
||||
use crate::render::RenderState;
|
||||
use std::ops::{Deref, Range};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CopySurfaceBufferNode {}
|
||||
|
||||
impl CopySurfaceBufferNode {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for CopySurfaceBufferNode {
|
||||
fn input(&self) -> Vec<SlotInfo> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn update(&mut self, _state: &mut RenderState) {}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
RenderContext {
|
||||
command_encoder, ..
|
||||
}: &mut RenderContext,
|
||||
state: &RenderState,
|
||||
) -> Result<(), NodeRunError> {
|
||||
match state.surface.head() {
|
||||
Head::Headed(_) => {}
|
||||
Head::Headless(buffered_texture) => {
|
||||
let size = state.surface.size();
|
||||
command_encoder.copy_texture_to_buffer(
|
||||
buffered_texture.texture.as_image_copy(),
|
||||
wgpu::ImageCopyBuffer {
|
||||
buffer: &buffered_texture.output_buffer,
|
||||
layout: wgpu::ImageDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(
|
||||
std::num::NonZeroU32::new(
|
||||
buffered_texture.buffer_dimensions.padded_bytes_per_row as u32,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
rows_per_image: None,
|
||||
},
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: size.width() as u32,
|
||||
height: size.height() as u32,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -609,9 +609,9 @@ mod tests {
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
state: &RenderState,
|
||||
_graph: &mut RenderGraphContext,
|
||||
_render_context: &mut RenderContext,
|
||||
_state: &RenderState,
|
||||
) -> Result<(), NodeRunError> {
|
||||
Ok(())
|
||||
}
|
||||
@ -682,9 +682,9 @@ mod tests {
|
||||
impl Node for MyNode {
|
||||
fn run(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
state: &RenderState,
|
||||
_graph: &mut RenderGraphContext,
|
||||
_render_context: &mut RenderContext,
|
||||
_state: &RenderState,
|
||||
) -> Result<(), NodeRunError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -5,12 +5,12 @@
|
||||
|
||||
use crate::render::graph::{Node, NodeRunError, RenderContext, RenderGraphContext, SlotInfo};
|
||||
use crate::render::render_commands::{DrawMasks, DrawTiles};
|
||||
use crate::render::render_phase::{PhaseItem, RenderCommand};
|
||||
use crate::render::render_phase::RenderCommand;
|
||||
use crate::render::resource::TrackedRenderPass;
|
||||
use crate::render::util::FloatOrd;
|
||||
|
||||
use crate::render::Eventually::Initialized;
|
||||
use crate::render::{draw_graph, main_graph, RenderState};
|
||||
use std::ops::{Deref, Range};
|
||||
use crate::render::{draw_graph, RenderState};
|
||||
use std::ops::Deref;
|
||||
|
||||
pub mod graph {
|
||||
// Labels for input nodes
|
||||
|
||||
@ -22,18 +22,15 @@ use crate::render::render_phase::RenderPhase;
|
||||
use crate::render::resource::{BufferPool, Globals, IndexEntry};
|
||||
use crate::render::resource::{Head, Surface};
|
||||
use crate::render::resource::{Texture, TextureView};
|
||||
use crate::render::settings::{RendererSettings, SurfaceType, WgpuSettings};
|
||||
use crate::render::settings::{RendererSettings, WgpuSettings};
|
||||
use crate::render::shaders::{ShaderFeatureStyle, ShaderLayerMetadata};
|
||||
use crate::render::tile_view_pattern::{TileInView, TileShape, TileViewPattern};
|
||||
use crate::render::util::Eventually;
|
||||
use crate::tessellation::IndexDataType;
|
||||
use crate::{HeadedMapWindow, MapWindow, MapWindowConfig};
|
||||
use crate::{HeadedMapWindow, MapWindow};
|
||||
use log::info;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
// Exposed because it should be addable conditionally
|
||||
pub mod copy_surface_to_buffer_node;
|
||||
pub mod graph;
|
||||
pub mod resource;
|
||||
pub mod stages;
|
||||
@ -52,8 +49,10 @@ mod util;
|
||||
pub mod camera;
|
||||
pub mod settings;
|
||||
|
||||
use crate::render::graph::{EmptyNode, RenderGraph, RenderGraphError};
|
||||
use crate::render::main_pass::{MainPassDriverNode, MainPassNode};
|
||||
pub use shaders::ShaderVertex;
|
||||
pub use stages::register_render_stages;
|
||||
pub use stages::register_default_render_stages;
|
||||
|
||||
pub const INDEX_FORMAT: wgpu::IndexFormat = wgpu::IndexFormat::Uint32; // Must match IndexDataType
|
||||
|
||||
@ -80,7 +79,7 @@ pub struct RenderState {
|
||||
depth_texture: Eventually<Texture>,
|
||||
multisampling_texture: Eventually<Option<Texture>>,
|
||||
|
||||
surface: Surface,
|
||||
pub surface: Surface,
|
||||
|
||||
mask_phase: RenderPhase<TileInView>,
|
||||
tile_phase: RenderPhase<(IndexEntry, TileShape)>,
|
||||
@ -380,11 +379,7 @@ impl Renderer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::render::graph::RenderGraph;
|
||||
use crate::render::graph_runner::RenderGraphRunner;
|
||||
use crate::render::resource::Surface;
|
||||
use crate::{MapWindow, MapWindowConfig, RenderState, Renderer, RendererSettings, WindowSize};
|
||||
use log::LevelFilter;
|
||||
use crate::{MapWindow, MapWindowConfig, WindowSize};
|
||||
|
||||
pub struct HeadlessMapWindowConfig {
|
||||
size: WindowSize,
|
||||
@ -411,6 +406,12 @@ mod tests {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[tokio::test]
|
||||
async fn test_render() {
|
||||
use crate::render::graph::RenderGraph;
|
||||
use crate::render::graph_runner::RenderGraphRunner;
|
||||
use crate::render::resource::Surface;
|
||||
use crate::{RenderState, RendererSettings};
|
||||
use log::LevelFilter;
|
||||
|
||||
let _ = env_logger::builder()
|
||||
.filter_level(LevelFilter::Trace)
|
||||
.is_test(true)
|
||||
@ -474,3 +475,22 @@ pub mod draw_graph {
|
||||
pub const COPY: &str = "copy";
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_default_render_graph() -> Result<RenderGraph, RenderGraphError> {
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
let mut draw_graph = RenderGraph::default();
|
||||
draw_graph.add_node(draw_graph::node::MAIN_PASS, MainPassNode::new());
|
||||
let input_node_id = draw_graph.set_input(vec![]);
|
||||
draw_graph.add_node_edge(input_node_id, draw_graph::node::MAIN_PASS)?;
|
||||
|
||||
graph.add_sub_graph(draw_graph::NAME, draw_graph);
|
||||
graph.add_node(main_graph::node::MAIN_PASS_DEPENDENCIES, EmptyNode);
|
||||
graph.add_node(main_graph::node::MAIN_PASS_DRIVER, MainPassDriverNode);
|
||||
graph.add_node_edge(
|
||||
main_graph::node::MAIN_PASS_DEPENDENCIES,
|
||||
main_graph::node::MAIN_PASS_DRIVER,
|
||||
)?;
|
||||
|
||||
Ok(graph)
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
use crate::render::resource::TrackedRenderPass;
|
||||
use crate::RenderState;
|
||||
use std::collections::HashMap;
|
||||
use std::{any::TypeId, fmt::Debug, hash::Hash};
|
||||
|
||||
/// A draw function which is used to draw a specific [`PhaseItem`].
|
||||
///
|
||||
|
||||
@ -5,9 +5,8 @@ use crate::render::resource::texture::TextureView;
|
||||
use crate::render::settings::RendererSettings;
|
||||
use crate::render::util::HasChanged;
|
||||
use crate::window::HeadedMapWindow;
|
||||
use crate::{MapWindow, MapWindowConfig, WindowSize};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use crate::{MapWindow, WindowSize};
|
||||
|
||||
use std::mem::size_of;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -69,6 +68,8 @@ impl BufferedTextureHead {
|
||||
png_output_path: &str,
|
||||
// device: &wgpu::Device,
|
||||
) {
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
// Note that we're not calling `.await` here.
|
||||
let buffer_slice = self.output_buffer.slice(..);
|
||||
let buffer_future = buffer_slice.map_async(wgpu::MapMode::Read, |_| ());
|
||||
|
||||
@ -1,19 +1,11 @@
|
||||
//! Extracts data from the current state.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::ViewProjection;
|
||||
use crate::render::render_phase::RenderPhase;
|
||||
use crate::render::resource::IndexEntry;
|
||||
use crate::render::shaders::{
|
||||
ShaderCamera, ShaderFeatureStyle, ShaderGlobals, ShaderLayerMetadata, Vec4f32,
|
||||
};
|
||||
use crate::render::tile_view_pattern::TileInView;
|
||||
use crate::coords::ViewRegion;
|
||||
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
use crate::schedule::Stage;
|
||||
use crate::{RenderState, Renderer, Style};
|
||||
use std::iter;
|
||||
use crate::{RenderState, Renderer};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ExtractStage;
|
||||
@ -27,8 +19,8 @@ impl Stage for ExtractStage {
|
||||
Renderer {
|
||||
state:
|
||||
RenderState {
|
||||
mask_phase,
|
||||
tile_phase,
|
||||
mask_phase: _,
|
||||
tile_phase: _,
|
||||
tile_view_pattern,
|
||||
buffer_pool,
|
||||
..
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
//! Executes the [`RenderGraph`] current render graph.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::render::graph::{EmptyNode, RenderGraph};
|
||||
use crate::render::graph::RenderGraph;
|
||||
use crate::render::graph_runner::RenderGraphRunner;
|
||||
use crate::render::main_pass::{MainPassDriverNode, MainPassNode};
|
||||
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
use crate::schedule::Stage;
|
||||
use crate::Renderer;
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::multi_stage;
|
||||
use crate::render::graph::{EmptyNode, RenderGraph, RenderGraphError};
|
||||
use crate::render::main_pass::{MainPassDriverNode, MainPassNode};
|
||||
use crate::render::graph::RenderGraph;
|
||||
|
||||
use crate::render::stages::extract_stage::ExtractStage;
|
||||
use crate::render::stages::phase_sort_stage::PhaseSortStage;
|
||||
use crate::render::stages::queue_stage::QueueStage;
|
||||
use crate::render::{draw_graph, main_graph};
|
||||
use crate::schedule::{MultiStage, Schedule, Stage, StageLabel};
|
||||
|
||||
use crate::schedule::{Schedule, Stage, StageLabel};
|
||||
use graph_runner_stage::GraphRunnerStage;
|
||||
use resource_stage::ResourceStage;
|
||||
use upload_stage::UploadStage;
|
||||
@ -20,10 +20,6 @@ mod queue_stage;
|
||||
mod resource_stage;
|
||||
mod upload_stage;
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
// Exposed because it should be addable conditionally
|
||||
pub mod write_surface_buffer_stage;
|
||||
|
||||
/// The labels of the default App rendering stages.
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
||||
pub enum RenderStageLabel {
|
||||
@ -60,45 +56,9 @@ multi_stage!(
|
||||
upload: UploadStage
|
||||
);
|
||||
|
||||
pub fn register_render_stages(
|
||||
schedule: &mut Schedule,
|
||||
headless: bool,
|
||||
) -> Result<(), RenderGraphError> {
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
let mut draw_graph = RenderGraph::default();
|
||||
draw_graph.add_node(draw_graph::node::MAIN_PASS, MainPassNode::new());
|
||||
let input_node_id = draw_graph.set_input(vec![]);
|
||||
draw_graph.add_node_edge(input_node_id, draw_graph::node::MAIN_PASS)?;
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
if headless {
|
||||
use crate::render::copy_surface_to_buffer_node::CopySurfaceBufferNode;
|
||||
draw_graph.add_node(draw_graph::node::COPY, CopySurfaceBufferNode::default());
|
||||
draw_graph.add_node_edge(draw_graph::node::MAIN_PASS, draw_graph::node::COPY)?;
|
||||
}
|
||||
|
||||
graph.add_sub_graph(draw_graph::NAME, draw_graph);
|
||||
graph.add_node(main_graph::node::MAIN_PASS_DEPENDENCIES, EmptyNode);
|
||||
graph.add_node(main_graph::node::MAIN_PASS_DRIVER, MainPassDriverNode);
|
||||
graph.add_node_edge(
|
||||
main_graph::node::MAIN_PASS_DEPENDENCIES,
|
||||
main_graph::node::MAIN_PASS_DRIVER,
|
||||
)?;
|
||||
|
||||
pub fn register_default_render_stages(graph: RenderGraph, schedule: &mut Schedule) {
|
||||
schedule.add_stage(RenderStageLabel::Prepare, PrepareStage::default());
|
||||
schedule.add_stage(RenderStageLabel::Queue, QueueStage::default());
|
||||
schedule.add_stage(RenderStageLabel::PhaseSort, PhaseSortStage::default());
|
||||
schedule.add_stage(RenderStageLabel::Render, GraphRunnerStage::new(graph));
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
if headless {
|
||||
use crate::render::stages::write_surface_buffer_stage::WriteSurfaceBufferStage;
|
||||
schedule.add_stage(
|
||||
RenderStageLabel::Cleanup,
|
||||
WriteSurfaceBufferStage::default(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,19 +1,11 @@
|
||||
//! Sorts items of the [RenderPhases](RenderPhase).
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::ViewProjection;
|
||||
|
||||
use crate::render::render_phase::RenderPhase;
|
||||
use crate::render::resource::IndexEntry;
|
||||
use crate::render::shaders::{
|
||||
ShaderCamera, ShaderFeatureStyle, ShaderGlobals, ShaderLayerMetadata, Vec4f32,
|
||||
};
|
||||
use crate::render::tile_view_pattern::TileInView;
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
|
||||
use crate::schedule::Stage;
|
||||
use crate::{RenderState, Renderer, Style};
|
||||
use std::iter;
|
||||
use crate::Renderer;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PhaseSortStage;
|
||||
|
||||
@ -1,18 +1,13 @@
|
||||
//! Queues [PhaseItems](crate::render::render_phase::PhaseItem) for rendering.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::ViewProjection;
|
||||
|
||||
use crate::render::resource::IndexEntry;
|
||||
use crate::render::shaders::{
|
||||
ShaderCamera, ShaderFeatureStyle, ShaderGlobals, ShaderLayerMetadata, Vec4f32,
|
||||
};
|
||||
|
||||
use crate::render::tile_view_pattern::TileInView;
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
use crate::schedule::Stage;
|
||||
use crate::{RenderState, Renderer, Style};
|
||||
use std::iter;
|
||||
use crate::{RenderState, Renderer};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct QueueStage;
|
||||
@ -22,7 +17,7 @@ impl Stage for QueueStage {
|
||||
fn run(
|
||||
&mut self,
|
||||
MapContext {
|
||||
view_state,
|
||||
view_state: _,
|
||||
renderer:
|
||||
Renderer {
|
||||
state:
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
//! Prepares GPU-owned resources by initializing them if they are uninitialized or out-of-date.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::platform::MIN_BUFFER_SIZE;
|
||||
|
||||
use crate::render::resource::Texture;
|
||||
use crate::render::resource::{BackingBufferDescriptor, BufferPool};
|
||||
use crate::render::resource::{Globals, RenderPipeline};
|
||||
use crate::render::shaders;
|
||||
use crate::render::shaders::{Shader, ShaderGlobals, ShaderTileMetadata};
|
||||
use crate::render::shaders::{Shader, ShaderTileMetadata};
|
||||
use crate::render::tile_pipeline::TilePipeline;
|
||||
use crate::render::tile_view_pattern::TileViewPattern;
|
||||
use crate::schedule::Stage;
|
||||
use crate::Renderer;
|
||||
use std::cmp;
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
pub const TILE_VIEW_SIZE: wgpu::BufferAddress = 32;
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
//! Uploads data to the GPU which is needed for rendering.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::coords::ViewRegion;
|
||||
use crate::io::tile_repository::{StoredLayer, TileRepository};
|
||||
use crate::render::camera::ViewProjection;
|
||||
use crate::render::resource::IndexEntry;
|
||||
|
||||
use crate::render::shaders::{
|
||||
ShaderCamera, ShaderFeatureStyle, ShaderGlobals, ShaderLayerMetadata, Vec4f32,
|
||||
};
|
||||
use crate::render::tile_view_pattern::TileInView;
|
||||
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
use crate::schedule::Stage;
|
||||
use crate::{RenderState, Renderer, Style};
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
//! Stage which writes the current contents of the GPU/CPU buffer in [`BufferedTextureHead`]
|
||||
//! to disk as PNG.
|
||||
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{ViewRegion, Zoom};
|
||||
use crate::io::tile_repository::TileRepository;
|
||||
use crate::render::camera::ViewProjection;
|
||||
use crate::render::render_phase::RenderPhase;
|
||||
use crate::render::resource::{BufferDimensions, BufferedTextureHead, Head, IndexEntry};
|
||||
use crate::render::shaders::{
|
||||
ShaderCamera, ShaderFeatureStyle, ShaderGlobals, ShaderLayerMetadata, Vec4f32,
|
||||
};
|
||||
use crate::render::tile_view_pattern::TileInView;
|
||||
use crate::render::util::Eventually::Initialized;
|
||||
use crate::schedule::Stage;
|
||||
use crate::{RenderState, Renderer, Style};
|
||||
use std::fs::File;
|
||||
use std::future::Future;
|
||||
use std::io::Write;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task;
|
||||
use wgpu::{BufferAsyncError, BufferSlice};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WriteSurfaceBufferStage {
|
||||
frame: u64,
|
||||
}
|
||||
|
||||
impl Stage for WriteSurfaceBufferStage {
|
||||
fn run(
|
||||
&mut self,
|
||||
MapContext {
|
||||
renderer: Renderer { state, device, .. },
|
||||
..
|
||||
}: &mut MapContext,
|
||||
) {
|
||||
match state.surface.head() {
|
||||
Head::Headed(_) => {}
|
||||
Head::Headless(buffered_texture) => {
|
||||
let buffered_texture: Arc<BufferedTextureHead> = buffered_texture.clone();
|
||||
|
||||
let device = device.clone();
|
||||
let current_frame = self.frame;
|
||||
|
||||
task::block_in_place(|| {
|
||||
Handle::current().block_on(async {
|
||||
buffered_texture
|
||||
.create_png(&device, format!("frame_{}.png", current_frame).as_str())
|
||||
.await;
|
||||
})
|
||||
});
|
||||
|
||||
self.frame += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,13 +68,7 @@ where
|
||||
#[tracing::instrument(name = "reinitialize", skip_all)]
|
||||
pub fn reinitialize(&mut self, f: impl FnOnce() -> T, criteria: &T::Criteria) {
|
||||
let should_replace = match &self {
|
||||
Eventually::Initialized(current) => {
|
||||
if current.has_changed(criteria) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Eventually::Initialized(current) => current.has_changed(criteria),
|
||||
Eventually::Uninitialized => true,
|
||||
};
|
||||
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
use crate::context::MapContext;
|
||||
use crate::define_label;
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use std::any::Any;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct NopStage;
|
||||
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
use crate::coords::{WorldCoords, WorldTileCoords, Zoom};
|
||||
use crate::error::Error;
|
||||
use crate::io::geometry_index::{GeometryIndex, IndexedGeometry};
|
||||
use crate::io::pipeline::PipelineContext;
|
||||
use crate::io::pipeline::Processable;
|
||||
use crate::io::tile_pipelines::build_vector_tile_pipeline;
|
||||
use crate::coords::WorldTileCoords;
|
||||
|
||||
use crate::io::tile_repository::StoredLayer;
|
||||
use crate::io::tile_request_state::TileRequestState;
|
||||
use crate::io::{TileRequest, TileRequestID};
|
||||
|
||||
use crate::io::TileRequestID;
|
||||
use crate::render::ShaderVertex;
|
||||
use crate::stages::HeadedPipelineProcessor;
|
||||
|
||||
use crate::tessellation::{IndexDataType, OverAlignedVertexBuffer};
|
||||
use geozero::mvt::tile;
|
||||
use std::fmt;
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub type MessageSender = mpsc::Sender<TessellateMessage>;
|
||||
pub type MessageReceiver = mpsc::Receiver<TessellateMessage>;
|
||||
|
||||
@ -4,12 +4,12 @@ use crate::coords::ZoomLevel;
|
||||
use crate::coords::{WorldCoords, WorldTileCoords, Zoom};
|
||||
use crate::error::Error;
|
||||
use crate::io::geometry_index::GeometryIndex;
|
||||
use crate::io::geometry_index::{IndexProcessor, IndexedGeometry, TileIndex};
|
||||
use crate::io::geometry_index::{IndexedGeometry, TileIndex};
|
||||
use crate::io::pipeline::Processable;
|
||||
use crate::io::pipeline::{PipelineContext, PipelineProcessor};
|
||||
use crate::io::source_client::{HttpSourceClient, SourceClient};
|
||||
use crate::io::source_client::HttpSourceClient;
|
||||
use crate::io::tile_pipelines::build_vector_tile_pipeline;
|
||||
use crate::io::tile_repository::StoredLayer;
|
||||
|
||||
use crate::io::tile_request_state::TileRequestState;
|
||||
use crate::io::{TileRequest, TileRequestID};
|
||||
use crate::render::ShaderVertex;
|
||||
@ -19,15 +19,14 @@ use crate::stages::message::{
|
||||
TileTessellateMessage,
|
||||
};
|
||||
use crate::stages::populate_tile_store_stage::PopulateTileStore;
|
||||
use crate::tessellation::zero_tessellator::ZeroTessellator;
|
||||
|
||||
use crate::tessellation::{IndexDataType, OverAlignedVertexBuffer};
|
||||
use crate::{HttpClient, ScheduleMethod, Scheduler};
|
||||
use geozero::mvt::tile;
|
||||
use geozero::GeozeroDatasource;
|
||||
use prost::Message;
|
||||
|
||||
use request_stage::RequestStage;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
|
||||
mod message;
|
||||
@ -110,7 +109,7 @@ impl PipelineProcessor for HeadedPipelineProcessor {
|
||||
geometries: Vec<IndexedGeometry<f64>>,
|
||||
) {
|
||||
if let Ok(mut geometry_index) = self.state.geometry_index.lock() {
|
||||
geometry_index.index_tile(&coords, TileIndex::Linear { list: geometries })
|
||||
geometry_index.index_tile(coords, TileIndex::Linear { list: geometries })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ use super::{MessageReceiver, SharedThreadState, TessellateMessage, TileTessellat
|
||||
use crate::context::MapContext;
|
||||
use crate::io::tile_repository::StoredLayer;
|
||||
use crate::schedule::Stage;
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub struct PopulateTileStore {
|
||||
shared_thread_state: SharedThreadState,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Utilities for the window system.
|
||||
|
||||
use crate::{HttpClient, InteractiveMapSchedule, ScheduleMethod};
|
||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
|
||||
/// Window of a certain [`WindowSize`]. This can either be a proper window or a headless one.
|
||||
pub trait MapWindow {
|
||||
|
||||
@ -4,7 +4,7 @@ use crate::platform::schedule_method::WebWorkerPoolScheduleMethod;
|
||||
use maplibre::io::scheduler::Scheduler;
|
||||
|
||||
use maplibre::MapBuilder;
|
||||
use maplibre_winit::winit::{WinitMapWindow, WinitMapWindowConfig};
|
||||
use maplibre_winit::winit::WinitMapWindowConfig;
|
||||
use std::panic;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user