Optimize viewer shaders and camera controls; sample GPU profiles asynchronously
Amp-Thread-ID: https://ampcode.com/threads/T-01a0b382-1e79-712b-abd1-d29201c9bb5e Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
+28
-39
@@ -10,26 +10,13 @@ use crate::render_data::RenderData;
|
||||
use crate::store::{Loadout, Store};
|
||||
|
||||
#[wasm_bindgen(inline_js = r#"
|
||||
const channel = new MessageChannel();
|
||||
const ready = [];
|
||||
channel.port1.onmessage = () => ready.shift()?.();
|
||||
|
||||
export function nextFrame() {
|
||||
return new Promise(resolve => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
export function yieldTask() {
|
||||
return new Promise(resolve => {
|
||||
ready.push(resolve);
|
||||
channel.port2.postMessage(0);
|
||||
});
|
||||
}
|
||||
"#)]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = nextFrame)]
|
||||
async fn next_frame();
|
||||
#[wasm_bindgen(js_name = yieldTask)]
|
||||
async fn yield_task();
|
||||
}
|
||||
|
||||
pub struct RenderLoop {
|
||||
@@ -42,7 +29,8 @@ pub struct RenderLoop {
|
||||
profiling: Cell<bool>,
|
||||
profile_pending: Cell<bool>,
|
||||
profile_after: Cell<f64>,
|
||||
profile: RefCell<Option<String>>,
|
||||
profile_callback: RefCell<Option<js_sys::Function>>,
|
||||
profile_generation: Cell<u32>,
|
||||
}
|
||||
|
||||
impl RenderLoop {
|
||||
@@ -57,7 +45,8 @@ impl RenderLoop {
|
||||
profiling: Cell::new(false),
|
||||
profile_pending: Cell::new(false),
|
||||
profile_after: Cell::new(0.0),
|
||||
profile: RefCell::new(None),
|
||||
profile_callback: RefCell::new(None),
|
||||
profile_generation: Cell::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +70,12 @@ impl RenderLoop {
|
||||
pub fn set_profiling(&self, enabled: bool) {
|
||||
self.profiling.set(enabled);
|
||||
self.profile_after.set(0.0);
|
||||
if !enabled {
|
||||
self.profile.borrow_mut().take();
|
||||
}
|
||||
self.profile_generation
|
||||
.set(self.profile_generation.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
pub fn take_profile(&self) -> Option<String> {
|
||||
self.profile.borrow_mut().take()
|
||||
pub fn on_profile(&self, callback: js_sys::Function) {
|
||||
*self.profile_callback.borrow_mut() = Some(callback);
|
||||
}
|
||||
|
||||
pub fn start(
|
||||
@@ -152,15 +140,12 @@ impl RenderLoop {
|
||||
};
|
||||
if let Some((profile, adapter, width, height)) = submission {
|
||||
control.profile_pending.set(true);
|
||||
control.profile_after.set(started + 250.0);
|
||||
control.profile_after.set(started + 100.0);
|
||||
let generation = control.profile_generation.get();
|
||||
let control = control.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
while profile.state() == 0 {
|
||||
yield_task().await;
|
||||
}
|
||||
if profile.state() == 1 {
|
||||
let passes = profile
|
||||
.read()
|
||||
if let Some(passes) = profile.read().await {
|
||||
let passes = passes
|
||||
.into_iter()
|
||||
.map(|(name, milliseconds)| {
|
||||
serde_json::json!({
|
||||
@@ -173,18 +158,22 @@ impl RenderLoop {
|
||||
.iter()
|
||||
.filter_map(|pass| pass["milliseconds"].as_f64())
|
||||
.sum::<f64>();
|
||||
if control.profiling.get() {
|
||||
*control.profile.borrow_mut() = Some(
|
||||
serde_json::json!({
|
||||
"frame": frame,
|
||||
"milliseconds": milliseconds,
|
||||
"readbackMilliseconds": js_sys::Date::now() - started,
|
||||
"adapter": adapter,
|
||||
"canvas": { "width": width, "height": height },
|
||||
"passes": passes,
|
||||
})
|
||||
.to_string(),
|
||||
);
|
||||
if control.profiling.get()
|
||||
&& control.profile_generation.get() == generation
|
||||
{
|
||||
let sample = serde_json::json!({
|
||||
"frame": frame,
|
||||
"milliseconds": milliseconds,
|
||||
"readbackMilliseconds": js_sys::Date::now() - started,
|
||||
"adapter": adapter,
|
||||
"canvas": { "width": width, "height": height },
|
||||
"passes": passes,
|
||||
})
|
||||
.to_string();
|
||||
if let Some(callback) = control.profile_callback.borrow().as_ref() {
|
||||
let _ = callback
|
||||
.call1(&wasm_bindgen::JsValue::NULL, &sample.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
control.profile_pending.set(false);
|
||||
|
||||
Reference in New Issue
Block a user