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::io::scheduler::ScheduleMethod;
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::run_multithreaded;
use maplibre::platform::schedule_method::TokioScheduleMethod;
@ -45,10 +45,6 @@ where
HC: HTTPClient,
{
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 {
match map_state.update_and_redraw() {
Ok(_) => {}

View File

@ -53,8 +53,8 @@ where
SM: ScheduleMethod,
HC: HTTPClient,
{
map_state: MapSchedule<W::MapWindowConfig, SM, HC>,
window: W,
map_state: MapSchedule<MWC, SM, HC>,
window: MWC::MapWindow,
}
impl<MWC, SM, HC> Map<MWC, SM, HC>
@ -115,14 +115,18 @@ where
{
/// Initializes the whole rendering pipeline for the given configuration.
/// Returns the initialized map, ready to be run.
pub async fn initialize(self) -> Map<MWC::MapWindow, SM, HC> {
let window = MWC::MapWindow::create(&self.map_window_config);
pub async fn initialize(self) -> Map<MWC, SM, HC>
where
MWC: MapWindowConfig,
<MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
{
let window = self.map_window_config.create();
let window_size = window.size();
#[cfg(target_os = "android")]
let renderer = None;
#[cfg(not(target_os = "android"))]
let renderer = Renderer::initialize(
let renderer = Renderer::initialize::<MWC>(
&window,
self.wgpu_settings.clone(),
self.renderer_settings.clone(),
@ -146,22 +150,25 @@ where
pub async fn initialize_headless(self) -> Map<MWC, SM, HC> {
let window = self.map_window_config.create();
let window_size = window.size();
let renderer = Renderer::initialize_headless::<MWC>(
&window,
self.wgpu_settings,
self.renderer_settings,
self.wgpu_settings.clone(),
self.renderer_settings.clone(),
)
.await
.unwrap();
.ok();
Map {
map_state: MapSchedule::new(
window.size(),
self.map_window_config,
Some(renderer),
window_size,
renderer,
self.scheduler,
self.http_client,
self.style,
self.wgpu_settings,
self.renderer_settings,
),
window,
}

View File

@ -14,22 +14,22 @@ use crate::schedule::{Schedule, Stage};
use crate::stages::register_stages;
use crate::style::Style;
use crate::{
MapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod, WgpuSettings,
WindowSize,
HeadedMapWindow, MapWindow, MapWindowConfig, Renderer, RendererSettings, ScheduleMethod,
WgpuSettings, WindowSize,
};
use std::marker::PhantomData;
use std::mem;
use std::sync::{mpsc, Arc, Mutex};
pub struct PrematureMapContext {
pub view_state: ViewState,
pub style: Style,
view_state: ViewState,
style: Style,
pub tile_cache: TileCache,
pub scheduler: Box<dyn ScheduleMethod>,
tile_cache: TileCache,
scheduler: Box<dyn ScheduleMethod>,
pub message_receiver: mpsc::Receiver<TessellateMessage>,
pub shared_thread_state: SharedThreadState,
message_receiver: mpsc::Receiver<TessellateMessage>,
shared_thread_state: SharedThreadState,
wgpu_settings: WgpuSettings,
renderer_settings: RendererSettings,
@ -183,13 +183,16 @@ where
self.suspended = true;
}
pub fn resume<MW>(&mut self, window: &MW)
pub fn resume(&mut self, window: &MWC::MapWindow)
where
MW: MapWindow,
<MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
{
if let EventuallyMapContext::Full(map_context) = &mut self.map_context {
let mut renderer = &mut map_context.renderer;
renderer.surface.recreate(window, &renderer.instance);
renderer
.state
.surface
.recreate::<MWC>(window, &renderer.instance);
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 {
EventuallyMapContext::Full(_) => false,
EventuallyMapContext::Premature(PrematureMapContext {
view_state,
style,
tile_cache,
scheduler,
message_receiver,
shared_thread_state,
wgpu_settings,
renderer_settings,
..
}) => {
let window = MWC::MapWindow::create(&self.map_window_config);
let renderer =
Renderer::initialize(&window, wgpu_settings.clone(), renderer_settings.clone())
.await
.unwrap();
let window = self.map_window_config.create();
let renderer = Renderer::initialize::<MWC>(
&window,
wgpu_settings.clone(),
renderer_settings.clone(),
)
.await
.unwrap();
&self.map_context.make_full(renderer);
true
}

View File

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

View File

@ -65,6 +65,7 @@ pub struct BufferedTextureHead {
impl BufferedTextureHead {
pub async fn create_png<'a>(
&self,
device: &wgpu::Device,
png_output_path: &str,
// device: &wgpu::Device,
) {
@ -75,7 +76,7 @@ impl BufferedTextureHead {
// Poll the device in a blocking manner so that our future resolves.
// In an actual application, `device.poll(...)` should
// 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 {
let padded_buffer = buffer_slice.get_mapped_range();

View File

@ -24,13 +24,15 @@ use tokio::task;
use wgpu::{BufferAsyncError, BufferSlice};
#[derive(Default)]
pub struct WriteSurfaceBufferStage;
pub struct WriteSurfaceBufferStage {
frame: u64,
}
impl Stage for WriteSurfaceBufferStage {
fn run(
&mut self,
MapContext {
renderer: Renderer { state, .. },
renderer: Renderer { state, device, .. },
..
}: &mut MapContext,
) {
@ -39,11 +41,18 @@ impl Stage for WriteSurfaceBufferStage {
Head::Headless(buffered_texture) => {
let buffered_texture = 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("test.png").await;
buffered_texture
.create_png(&device, format!("frame_{}.png", current_frame).as_str())
.await;
})
});
self.frame += 1;
}
}
}