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