Simplify and fix headless rendering

This commit is contained in:
Maximilian Ammann 2022-05-23 15:57:19 +02:00
parent 355977e3b7
commit 03f38c2725
6 changed files with 60 additions and 43 deletions

View File

@ -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(_) => {}

View File

@ -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,
} }

View File

@ -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
} }

View File

@ -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)>,

View File

@ -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();

View File

@ -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;
} }
} }
} }