mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Simplify and fix headless rendering
This commit is contained in:
parent
355977e3b7
commit
03f38c2725
@ -1,7 +1,7 @@
|
|||||||
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 maplibre::map_state::MapSchedule;
|
use maplibre::map_schedule::MapSchedule;
|
||||||
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;
|
||||||
@ -45,10 +45,6 @@ where
|
|||||||
HC: HTTPClient,
|
HC: HTTPClient,
|
||||||
{
|
{
|
||||||
fn run(mut self, mut map_state: MapSchedule<MWC, SM, HC>, max_frames: Option<u64>) {
|
fn run(mut self, mut map_state: MapSchedule<MWC, SM, HC>, max_frames: Option<u64>) {
|
||||||
let arc = map_state.map_context.renderer.device.clone();
|
|
||||||
tokio::task::spawn_blocking(move || loop {
|
|
||||||
arc.poll(wgpu::Maintain::Wait);
|
|
||||||
});
|
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
match map_state.update_and_redraw() {
|
match map_state.update_and_redraw() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
|
|||||||
@ -53,8 +53,8 @@ where
|
|||||||
SM: ScheduleMethod,
|
SM: ScheduleMethod,
|
||||||
HC: HTTPClient,
|
HC: HTTPClient,
|
||||||
{
|
{
|
||||||
map_state: MapSchedule<W::MapWindowConfig, SM, HC>,
|
map_state: MapSchedule<MWC, SM, HC>,
|
||||||
window: W,
|
window: MWC::MapWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MWC, SM, HC> Map<MWC, SM, HC>
|
impl<MWC, SM, HC> Map<MWC, SM, HC>
|
||||||
@ -115,14 +115,18 @@ where
|
|||||||
{
|
{
|
||||||
/// Initializes the whole rendering pipeline for the given configuration.
|
/// Initializes the whole rendering pipeline for the given configuration.
|
||||||
/// Returns the initialized map, ready to be run.
|
/// Returns the initialized map, ready to be run.
|
||||||
pub async fn initialize(self) -> Map<MWC::MapWindow, SM, HC> {
|
pub async fn initialize(self) -> Map<MWC, SM, HC>
|
||||||
let window = MWC::MapWindow::create(&self.map_window_config);
|
where
|
||||||
|
MWC: MapWindowConfig,
|
||||||
|
<MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
|
||||||
|
{
|
||||||
|
let window = self.map_window_config.create();
|
||||||
let window_size = window.size();
|
let window_size = window.size();
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
let renderer = None;
|
let renderer = None;
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let renderer = Renderer::initialize(
|
let renderer = Renderer::initialize::<MWC>(
|
||||||
&window,
|
&window,
|
||||||
self.wgpu_settings.clone(),
|
self.wgpu_settings.clone(),
|
||||||
self.renderer_settings.clone(),
|
self.renderer_settings.clone(),
|
||||||
@ -146,22 +150,25 @@ where
|
|||||||
|
|
||||||
pub async fn initialize_headless(self) -> Map<MWC, SM, HC> {
|
pub async fn initialize_headless(self) -> Map<MWC, SM, HC> {
|
||||||
let window = self.map_window_config.create();
|
let window = self.map_window_config.create();
|
||||||
|
let window_size = window.size();
|
||||||
|
|
||||||
let renderer = Renderer::initialize_headless::<MWC>(
|
let renderer = Renderer::initialize_headless::<MWC>(
|
||||||
&window,
|
&window,
|
||||||
self.wgpu_settings,
|
self.wgpu_settings.clone(),
|
||||||
self.renderer_settings,
|
self.renderer_settings.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.ok();
|
||||||
Map {
|
Map {
|
||||||
map_state: MapSchedule::new(
|
map_state: MapSchedule::new(
|
||||||
window.size(),
|
|
||||||
self.map_window_config,
|
self.map_window_config,
|
||||||
Some(renderer),
|
window_size,
|
||||||
|
renderer,
|
||||||
self.scheduler,
|
self.scheduler,
|
||||||
self.http_client,
|
self.http_client,
|
||||||
self.style,
|
self.style,
|
||||||
|
self.wgpu_settings,
|
||||||
|
self.renderer_settings,
|
||||||
),
|
),
|
||||||
window,
|
window,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,22 +14,22 @@ 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::{
|
||||||
MapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod, WgpuSettings,
|
HeadedMapWindow, MapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod,
|
||||||
WindowSize,
|
WgpuSettings, WindowSize,
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::{mpsc, Arc, Mutex};
|
use std::sync::{mpsc, Arc, Mutex};
|
||||||
|
|
||||||
pub struct PrematureMapContext {
|
pub struct PrematureMapContext {
|
||||||
pub view_state: ViewState,
|
view_state: ViewState,
|
||||||
pub style: Style,
|
style: Style,
|
||||||
|
|
||||||
pub tile_cache: TileCache,
|
tile_cache: TileCache,
|
||||||
pub scheduler: Box<dyn ScheduleMethod>,
|
scheduler: Box<dyn ScheduleMethod>,
|
||||||
|
|
||||||
pub message_receiver: mpsc::Receiver<TessellateMessage>,
|
message_receiver: mpsc::Receiver<TessellateMessage>,
|
||||||
pub shared_thread_state: SharedThreadState,
|
shared_thread_state: SharedThreadState,
|
||||||
|
|
||||||
wgpu_settings: WgpuSettings,
|
wgpu_settings: WgpuSettings,
|
||||||
renderer_settings: RendererSettings,
|
renderer_settings: RendererSettings,
|
||||||
@ -183,13 +183,16 @@ where
|
|||||||
self.suspended = true;
|
self.suspended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resume<MW>(&mut self, window: &MW)
|
pub fn resume(&mut self, window: &MWC::MapWindow)
|
||||||
where
|
where
|
||||||
MW: MapWindow,
|
<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 mut renderer = &mut map_context.renderer;
|
||||||
renderer.surface.recreate(window, &renderer.instance);
|
renderer
|
||||||
|
.state
|
||||||
|
.surface
|
||||||
|
.recreate::<MWC>(window, &renderer.instance);
|
||||||
self.suspended = false;
|
self.suspended = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,24 +204,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn late_init(&mut self) -> bool {
|
pub async fn late_init(&mut self) -> bool
|
||||||
|
where
|
||||||
|
<MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
|
||||||
|
{
|
||||||
match &self.map_context {
|
match &self.map_context {
|
||||||
EventuallyMapContext::Full(_) => false,
|
EventuallyMapContext::Full(_) => false,
|
||||||
EventuallyMapContext::Premature(PrematureMapContext {
|
EventuallyMapContext::Premature(PrematureMapContext {
|
||||||
view_state,
|
|
||||||
style,
|
|
||||||
tile_cache,
|
|
||||||
scheduler,
|
|
||||||
message_receiver,
|
|
||||||
shared_thread_state,
|
|
||||||
wgpu_settings,
|
wgpu_settings,
|
||||||
renderer_settings,
|
renderer_settings,
|
||||||
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let window = MWC::MapWindow::create(&self.map_window_config);
|
let window = self.map_window_config.create();
|
||||||
let renderer =
|
let renderer = Renderer::initialize::<MWC>(
|
||||||
Renderer::initialize(&window, wgpu_settings.clone(), renderer_settings.clone())
|
&window,
|
||||||
.await
|
wgpu_settings.clone(),
|
||||||
.unwrap();
|
renderer_settings.clone(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
&self.map_context.make_full(renderer);
|
&self.map_context.make_full(renderer);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,7 +77,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)>,
|
||||||
|
|||||||
@ -65,6 +65,7 @@ pub struct BufferedTextureHead {
|
|||||||
impl BufferedTextureHead {
|
impl BufferedTextureHead {
|
||||||
pub async fn create_png<'a>(
|
pub async fn create_png<'a>(
|
||||||
&self,
|
&self,
|
||||||
|
device: &wgpu::Device,
|
||||||
png_output_path: &str,
|
png_output_path: &str,
|
||||||
// device: &wgpu::Device,
|
// device: &wgpu::Device,
|
||||||
) {
|
) {
|
||||||
@ -75,7 +76,7 @@ impl BufferedTextureHead {
|
|||||||
// Poll the device in a blocking manner so that our future resolves.
|
// Poll the device in a blocking manner so that our future resolves.
|
||||||
// In an actual application, `device.poll(...)` should
|
// In an actual application, `device.poll(...)` should
|
||||||
// be called in an event loop or on another thread.
|
// be called in an event loop or on another thread.
|
||||||
//device.poll(wgpu::Maintain::Wait);
|
device.poll(wgpu::Maintain::Wait);
|
||||||
if let Ok(()) = buffer_future.await {
|
if let Ok(()) = buffer_future.await {
|
||||||
let padded_buffer = buffer_slice.get_mapped_range();
|
let padded_buffer = buffer_slice.get_mapped_range();
|
||||||
|
|
||||||
|
|||||||
@ -24,13 +24,15 @@ use tokio::task;
|
|||||||
use wgpu::{BufferAsyncError, BufferSlice};
|
use wgpu::{BufferAsyncError, BufferSlice};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WriteSurfaceBufferStage;
|
pub struct WriteSurfaceBufferStage {
|
||||||
|
frame: u64,
|
||||||
|
}
|
||||||
|
|
||||||
impl Stage for WriteSurfaceBufferStage {
|
impl Stage for WriteSurfaceBufferStage {
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
MapContext {
|
MapContext {
|
||||||
renderer: Renderer { state, .. },
|
renderer: Renderer { state, device, .. },
|
||||||
..
|
..
|
||||||
}: &mut MapContext,
|
}: &mut MapContext,
|
||||||
) {
|
) {
|
||||||
@ -39,11 +41,18 @@ impl Stage for WriteSurfaceBufferStage {
|
|||||||
Head::Headless(buffered_texture) => {
|
Head::Headless(buffered_texture) => {
|
||||||
let buffered_texture = buffered_texture.clone();
|
let buffered_texture = buffered_texture.clone();
|
||||||
|
|
||||||
|
let device = device.clone();
|
||||||
|
let current_frame = self.frame;
|
||||||
|
|
||||||
task::block_in_place(|| {
|
task::block_in_place(|| {
|
||||||
Handle::current().block_on(async {
|
Handle::current().block_on(async {
|
||||||
buffered_texture.create_png("test.png").await;
|
buffered_texture
|
||||||
|
.create_png(&device, format!("frame_{}.png", current_frame).as_str())
|
||||||
|
.await;
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.frame += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user