зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 419be9960357 (bug 1561367) for causing wrench bustages CLOSED TREE
This commit is contained in:
Родитель
86d843e1cc
Коммит
84357fecdc
|
@ -15,9 +15,6 @@ var gGfxUtils = {
|
|||
init() {
|
||||
if (Services.prefs.getBoolPref("gfx.webrender.enable-capture")) {
|
||||
document.getElementById("wrCaptureCmd").removeAttribute("disabled");
|
||||
document
|
||||
.getElementById("wrToggleCaptureSequenceCmd")
|
||||
.removeAttribute("disabled");
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -34,13 +31,6 @@ var gGfxUtils = {
|
|||
webrenderCapture() {
|
||||
window.windowUtils.wrCapture();
|
||||
},
|
||||
/**
|
||||
* Trigger a WebRender capture of the current state and future state
|
||||
* into a local folder. If called again, it will stop capturing.
|
||||
*/
|
||||
toggleWebrenderCaptureSequence() {
|
||||
window.windowUtils.wrToggleCaptureSequence();
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle transaction logging to text file.
|
||||
|
|
|
@ -103,7 +103,6 @@
|
|||
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
|
||||
|
||||
<command id="wrCaptureCmd" oncommand="gGfxUtils.webrenderCapture();" disabled="true"/>
|
||||
<command id="wrToggleCaptureSequenceCmd" oncommand="gGfxUtils.toggleWebrenderCaptureSequence();" disabled="true"/>
|
||||
#ifdef NIGHTLY_BUILD
|
||||
<command id="windowRecordingCmd" oncommand="gGfxUtils.toggleWindowRecording();"/>
|
||||
<command id="wrTransactionLoggingCmd" oncommand="gGfxUtils.toggleTransactionLogging();"/>
|
||||
|
@ -339,13 +338,6 @@
|
|||
key="#" modifiers="control"
|
||||
#endif
|
||||
command="wrCaptureCmd"/>
|
||||
<key id="key_wrToggleCaptureSequenceCmd"
|
||||
#ifdef XP_MACOSX
|
||||
key="6" modifiers="control,shift"
|
||||
#else
|
||||
key="^" modifiers="control"
|
||||
#endif
|
||||
command="wrToggleCaptureSequenceCmd"/>
|
||||
#ifdef NIGHTLY_BUILD
|
||||
<key id="key_windowRecordingCmd"
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -4113,14 +4113,6 @@ nsDOMWindowUtils::WrCapture() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::WrToggleCaptureSequence() {
|
||||
if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
|
||||
wrbc->ToggleCaptureSequence();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetCompositionRecording(bool aValue, Promise** aOutPromise) {
|
||||
return aValue ? StartCompositionRecording(aOutPromise)
|
||||
|
|
|
@ -1945,14 +1945,6 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
*/
|
||||
void wrCapture();
|
||||
|
||||
/**
|
||||
* Start capturing the contents of the current WebRender frame and
|
||||
* save them to a folder relative to the current working directory,
|
||||
* as well as any frames generated from this point onward. If called
|
||||
* again, it will stop capturing.
|
||||
*/
|
||||
void wrToggleCaptureSequence();
|
||||
|
||||
/**
|
||||
* Toggle recording of composition on and off.
|
||||
*
|
||||
|
|
|
@ -74,8 +74,6 @@ parent:
|
|||
async ScheduleComposite();
|
||||
// Save the frame capture to disk
|
||||
async Capture();
|
||||
// Start capturing each frame and save to disk, and if already started, stop.
|
||||
async ToggleCaptureSequence();
|
||||
|
||||
// Enable/Disable transaction logging
|
||||
async SetTransactionLogging(bool aValue);
|
||||
|
|
|
@ -616,9 +616,6 @@ void WebRenderBridgeChild::DeallocResourceShmem(RefCountedShmem& aShm) {
|
|||
}
|
||||
|
||||
void WebRenderBridgeChild::Capture() { this->SendCapture(); }
|
||||
void WebRenderBridgeChild::ToggleCaptureSequence() {
|
||||
this->SendToggleCaptureSequence();
|
||||
}
|
||||
|
||||
void WebRenderBridgeChild::SetTransactionLogging(bool aValue) {
|
||||
this->SendSetTransactionLogging(aValue);
|
||||
|
|
|
@ -182,7 +182,6 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
|
|||
void DeallocResourceShmem(RefCountedShmem& aShm);
|
||||
|
||||
void Capture();
|
||||
void ToggleCaptureSequence();
|
||||
void SetTransactionLogging(bool aValue);
|
||||
|
||||
private:
|
||||
|
|
|
@ -2156,13 +2156,6 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvToggleCaptureSequence() {
|
||||
if (!mDestroyed) {
|
||||
mApis[wr::RenderRoot::Default]->ToggleCaptureSequence();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetTransactionLogging(
|
||||
const bool& aValue) {
|
||||
if (!mDestroyed) {
|
||||
|
|
|
@ -193,7 +193,6 @@ class WebRenderBridgeParent final
|
|||
mozilla::ipc::IPCResult RecvInvalidateRenderedFrame() override;
|
||||
mozilla::ipc::IPCResult RecvScheduleComposite() override;
|
||||
mozilla::ipc::IPCResult RecvCapture() override;
|
||||
mozilla::ipc::IPCResult RecvToggleCaptureSequence() override;
|
||||
mozilla::ipc::IPCResult RecvSetTransactionLogging(const bool&) override;
|
||||
mozilla::ipc::IPCResult RecvSyncWithCompositor() override;
|
||||
|
||||
|
|
|
@ -375,7 +375,6 @@ WebRenderAPI::WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId,
|
|||
mUseANGLE(aUseANGLE),
|
||||
mUseDComp(aUseDComp),
|
||||
mUseTripleBuffering(aUseTripleBuffering),
|
||||
mCaptureSequence(false),
|
||||
mSyncHandle(aSyncHandle),
|
||||
mRenderRoot(aRenderRoot) {}
|
||||
|
||||
|
@ -649,22 +648,11 @@ void WebRenderAPI::WaitFlushed() {
|
|||
void WebRenderAPI::Capture() {
|
||||
// see CaptureBits
|
||||
// SCENE | FRAME | TILE_CACHE
|
||||
uint8_t bits = 15; // TODO: get from JavaScript
|
||||
uint8_t bits = 7; // TODO: get from JavaScript
|
||||
const char* path = "wr-capture"; // TODO: get from JavaScript
|
||||
wr_api_capture(mDocHandle, path, bits);
|
||||
}
|
||||
|
||||
void WebRenderAPI::ToggleCaptureSequence() {
|
||||
mCaptureSequence = !mCaptureSequence;
|
||||
if (mCaptureSequence) {
|
||||
uint8_t bits = 9; // TODO: get from JavaScript
|
||||
const char* path = "wr-capture-sequence"; // TODO: get from JavaScript
|
||||
wr_api_start_capture_sequence(mDocHandle, path, bits);
|
||||
} else {
|
||||
wr_api_stop_capture_sequence(mDocHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRenderAPI::SetTransactionLogging(bool aValue) {
|
||||
wr_api_set_transaction_logging(mDocHandle, aValue);
|
||||
}
|
||||
|
|
|
@ -279,9 +279,6 @@ class WebRenderAPI final {
|
|||
layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
|
||||
|
||||
void Capture();
|
||||
|
||||
void ToggleCaptureSequence();
|
||||
|
||||
void SetTransactionLogging(bool aValue);
|
||||
|
||||
void SetCompositionRecorder(
|
||||
|
@ -325,7 +322,6 @@ class WebRenderAPI final {
|
|||
bool mUseANGLE;
|
||||
bool mUseDComp;
|
||||
bool mUseTripleBuffering;
|
||||
bool mCaptureSequence;
|
||||
layers::SyncHandle mSyncHandle;
|
||||
wr::RenderRoot mRenderRoot;
|
||||
|
||||
|
|
|
@ -2003,8 +2003,9 @@ pub extern "C" fn wr_resource_updates_add_raw_font(
|
|||
txn.add_raw_font(key, bytes.flush_into_vec(), index);
|
||||
}
|
||||
|
||||
fn generate_capture_path(path: *const c_char) -> Option<PathBuf> {
|
||||
use std::fs::{File, create_dir_all};
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_api_capture(dh: &mut DocumentHandle, path: *const c_char, bits_raw: u32) {
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::Write;
|
||||
|
||||
let cstr = unsafe { CStr::from_ptr(path) };
|
||||
|
@ -2052,34 +2053,12 @@ fn generate_capture_path(path: *const c_char) -> Option<PathBuf> {
|
|||
}
|
||||
Err(e) => {
|
||||
warn!("Unable to create path '{:?}' for capture: {:?}", path, e);
|
||||
return None
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Some(path)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_api_capture(dh: &mut DocumentHandle, path: *const c_char, bits_raw: u32) {
|
||||
if let Some(path) = generate_capture_path(path) {
|
||||
let bits = CaptureBits::from_bits(bits_raw as _).unwrap();
|
||||
dh.api.save_capture(path, bits);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_api_start_capture_sequence(dh: &mut DocumentHandle, path: *const c_char, bits_raw: u32) {
|
||||
if let Some(path) = generate_capture_path(path) {
|
||||
let bits = CaptureBits::from_bits(bits_raw as _).unwrap();
|
||||
dh.api.start_capture_sequence(path, bits);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_api_stop_capture_sequence(dh: &mut DocumentHandle) {
|
||||
let border = "--------------------------\n";
|
||||
warn!("{} Stop capturing WR state\n{}", &border, &border);
|
||||
dh.api.stop_capture_sequence();
|
||||
let bits = CaptureBits::from_bits(bits_raw as _).unwrap();
|
||||
dh.api.save_capture(path, bits);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -21,12 +21,6 @@ use serde;
|
|||
pub struct CaptureConfig {
|
||||
pub root: PathBuf,
|
||||
pub bits: CaptureBits,
|
||||
/// Scene sequence ID when capturing multiple frames. Zero for a single frame capture.
|
||||
pub scene_id: u32,
|
||||
/// Frame sequence ID when capturing multiple frames. Zero for a single frame capture.
|
||||
pub frame_id: u32,
|
||||
/// Resource sequence ID when capturing multiple frames. Zero for a single frame capture.
|
||||
pub resource_id: u32,
|
||||
#[cfg(feature = "capture")]
|
||||
pretty: ron::ser::PrettyConfig,
|
||||
}
|
||||
|
@ -37,9 +31,6 @@ impl CaptureConfig {
|
|||
CaptureConfig {
|
||||
root,
|
||||
bits,
|
||||
scene_id: 0,
|
||||
frame_id: 0,
|
||||
resource_id: 0,
|
||||
#[cfg(feature = "capture")]
|
||||
pretty: ron::ser::PrettyConfig {
|
||||
enumerate_arrays: true,
|
||||
|
@ -49,111 +40,35 @@ impl CaptureConfig {
|
|||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn prepare_scene(&mut self) {
|
||||
use std::fs::create_dir_all;
|
||||
self.scene_id += 1;
|
||||
let _ = create_dir_all(&self.scene_root());
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn prepare_frame(&mut self) {
|
||||
use std::fs::create_dir_all;
|
||||
self.frame_id += 1;
|
||||
let _ = create_dir_all(&self.frame_root());
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn prepare_resource(&mut self) {
|
||||
use std::fs::create_dir_all;
|
||||
self.resource_id += 1;
|
||||
let _ = create_dir_all(&self.resource_root());
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
pub fn scene_root(&self) -> PathBuf {
|
||||
if self.scene_id > 0 {
|
||||
let path = format!("scenes/{:05}", self.scene_id);
|
||||
self.root.join(path)
|
||||
} else {
|
||||
self.root.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
pub fn frame_root(&self) -> PathBuf {
|
||||
if self.frame_id > 0 {
|
||||
let path = format!("frames/{:05}", self.frame_id);
|
||||
self.scene_root().join(path)
|
||||
} else {
|
||||
self.root.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
pub fn resource_root(&self) -> PathBuf {
|
||||
if self.resource_id > 0 {
|
||||
let path = format!("resources/{:05}", self.resource_id);
|
||||
self.root.join(path)
|
||||
} else {
|
||||
self.root.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn serialize_for_scene<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: serde::Serialize,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
self.serialize(data, self.scene_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn serialize_for_frame<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: serde::Serialize,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
self.serialize(data, self.frame_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn serialize_for_resource<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: serde::Serialize,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
self.serialize(data, self.resource_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn file_path_for_frame<P>(&self, name: P, ext: &str) -> PathBuf
|
||||
pub fn file_path<P>(&self, name: P, ext: &str) -> PathBuf
|
||||
where P: AsRef<Path> {
|
||||
self.frame_root().join(name).with_extension(ext)
|
||||
self.root.join(name).with_extension(ext)
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn serialize<T, P>(&self, data: &T, path: PathBuf, name: P)
|
||||
pub fn serialize<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: serde::Serialize,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
use std::io::Write;
|
||||
|
||||
let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
|
||||
.unwrap();
|
||||
let mut file = File::create(path.join(name).with_extension("ron"))
|
||||
let path = self.file_path(name, "ron");
|
||||
let mut file = File::create(path)
|
||||
.unwrap();
|
||||
write!(file, "{}\n", ron)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn serialize_tree<T, P>(data: &T, root: PathBuf, name: P)
|
||||
pub fn serialize_tree<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: PrintableTree,
|
||||
P: AsRef<Path>
|
||||
{
|
||||
let path = root
|
||||
let path = self.root
|
||||
.join(name)
|
||||
.with_extension("tree");
|
||||
let file = File::create(path)
|
||||
|
@ -162,17 +77,8 @@ impl CaptureConfig {
|
|||
data.print_with(&mut pt);
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn serialize_tree_for_frame<T, P>(&self, data: &T, name: P)
|
||||
where
|
||||
T: PrintableTree,
|
||||
P: AsRef<Path>
|
||||
{
|
||||
Self::serialize_tree(data, self.frame_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
|
||||
pub fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
|
||||
where
|
||||
T: for<'a> serde::Deserialize<'a>,
|
||||
P: AsRef<Path>,
|
||||
|
@ -193,33 +99,6 @@ impl CaptureConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub fn deserialize_for_scene<T, P>(&self, name: P) -> Option<T>
|
||||
where
|
||||
T: for<'a> serde::Deserialize<'a>,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Self::deserialize(&self.scene_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub fn deserialize_for_frame<T, P>(&self, name: P) -> Option<T>
|
||||
where
|
||||
T: for<'a> serde::Deserialize<'a>,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Self::deserialize(&self.frame_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub fn deserialize_for_resource<T, P>(&self, name: P) -> Option<T>
|
||||
where
|
||||
T: for<'a> serde::Deserialize<'a>,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
Self::deserialize(&self.resource_root(), name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "png")]
|
||||
pub fn save_png(
|
||||
path: PathBuf, size: DeviceIntSize, format: ImageFormat, stride: Option<i32>, data: &[u8],
|
||||
|
|
|
@ -540,7 +540,7 @@ pub enum DebugOutput {
|
|||
#[cfg(feature = "capture")]
|
||||
SaveCapture(CaptureConfig, Vec<ExternalCaptureImage>),
|
||||
#[cfg(feature = "replay")]
|
||||
LoadCapture(CaptureConfig, Vec<PlainExternalImage>),
|
||||
LoadCapture(PathBuf, Vec<PlainExternalImage>),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
@ -16,13 +16,11 @@ use api::{NotificationRequest, Checkpoint, QualitySettings};
|
|||
use api::{ClipIntern, FilterDataIntern, PrimitiveKeyKind};
|
||||
use api::channel::Payload;
|
||||
use api::units::*;
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
#[cfg(feature = "capture")]
|
||||
use api::CaptureBits;
|
||||
#[cfg(feature = "replay")]
|
||||
use api::CapturedDocument;
|
||||
use crate::spatial_tree::SpatialNodeIndex;
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use crate::capture::CaptureConfig;
|
||||
use crate::composite::{CompositorKind, CompositeDescriptor};
|
||||
#[cfg(feature = "debugger")]
|
||||
use crate::debug_server;
|
||||
|
@ -45,7 +43,7 @@ use crate::renderer::{AsyncPropertySampler, PipelineInfo};
|
|||
use crate::resource_cache::ResourceCache;
|
||||
#[cfg(feature = "replay")]
|
||||
use crate::resource_cache::PlainCacheOwn;
|
||||
#[cfg(feature = "replay")]
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use crate::resource_cache::PlainResources;
|
||||
#[cfg(feature = "replay")]
|
||||
use crate::scene::Scene;
|
||||
|
@ -55,8 +53,6 @@ use crate::scene_builder_thread::*;
|
|||
use serde::{Serialize, Deserialize};
|
||||
#[cfg(feature = "debugger")]
|
||||
use serde_json;
|
||||
#[cfg(feature = "replay")]
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
@ -745,7 +741,7 @@ struct PlainRenderBackend {
|
|||
default_device_pixel_ratio: f32,
|
||||
frame_config: FrameBuilderConfig,
|
||||
documents: FastHashMap<DocumentId, DocumentView>,
|
||||
resource_sequence_id: u32,
|
||||
resources: PlainResources,
|
||||
}
|
||||
|
||||
/// The render backend is responsible for transforming high level display lists into
|
||||
|
@ -778,10 +774,6 @@ pub struct RenderBackend {
|
|||
namespace_alloc_by_client: bool,
|
||||
|
||||
recycler: Recycler,
|
||||
#[cfg(feature = "capture")]
|
||||
capture_config: Option<CaptureConfig>,
|
||||
#[cfg(feature = "replay")]
|
||||
loaded_resource_sequence_id: u32,
|
||||
}
|
||||
|
||||
impl RenderBackend {
|
||||
|
@ -822,10 +814,6 @@ impl RenderBackend {
|
|||
debug_flags,
|
||||
namespace_alloc_by_client,
|
||||
recycler: Recycler::new(),
|
||||
#[cfg(feature = "capture")]
|
||||
capture_config: None,
|
||||
#[cfg(feature = "replay")]
|
||||
loaded_resource_sequence_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -939,38 +927,97 @@ impl RenderBackend {
|
|||
|
||||
while let Ok(msg) = self.scene_rx.try_recv() {
|
||||
match msg {
|
||||
SceneBuilderResult::Transactions(txns, result_tx) => {
|
||||
self.process_transaction(
|
||||
txns,
|
||||
result_tx,
|
||||
SceneBuilderResult::Transactions(mut txns, result_tx) => {
|
||||
self.prepare_for_frames();
|
||||
self.maybe_force_nop_documents(
|
||||
&mut frame_counter,
|
||||
&mut profile_counters,
|
||||
);
|
||||
self.bookkeep_after_frames();
|
||||
},
|
||||
#[cfg(feature = "capture")]
|
||||
SceneBuilderResult::CapturedTransactions(txns, capture_config, result_tx) => {
|
||||
if let Some(ref mut old_config) = self.capture_config {
|
||||
assert!(old_config.scene_id <= capture_config.scene_id);
|
||||
if old_config.scene_id < capture_config.scene_id {
|
||||
old_config.scene_id = capture_config.scene_id;
|
||||
old_config.frame_id = 0;
|
||||
|document_id| txns.iter().any(|txn| txn.document_id == document_id));
|
||||
|
||||
for mut txn in txns.drain(..) {
|
||||
let has_built_scene = txn.built_scene.is_some();
|
||||
|
||||
if let Some(timings) = txn.timings {
|
||||
if has_built_scene {
|
||||
profile_counters.scene_changed = true;
|
||||
}
|
||||
|
||||
profile_counters.txn.set(
|
||||
timings.builder_start_time_ns,
|
||||
timings.builder_end_time_ns,
|
||||
timings.send_time_ns,
|
||||
timings.scene_build_start_time_ns,
|
||||
timings.scene_build_end_time_ns,
|
||||
timings.display_list_len,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.capture_config = Some(capture_config);
|
||||
|
||||
if let Some(doc) = self.documents.get_mut(&txn.document_id) {
|
||||
|
||||
doc.removed_pipelines.append(&mut txn.removed_pipelines);
|
||||
|
||||
if let Some(built_scene) = txn.built_scene.take() {
|
||||
doc.new_async_scene_ready(
|
||||
built_scene,
|
||||
&mut self.recycler,
|
||||
);
|
||||
}
|
||||
|
||||
// If there are any additions or removals of clip modes
|
||||
// during the scene build, apply them to the data store now.
|
||||
// This needs to happen before we build the hit tester.
|
||||
if let Some(updates) = txn.interner_updates.take() {
|
||||
#[cfg(feature = "capture")]
|
||||
{
|
||||
if self.debug_flags.contains(DebugFlags::TILE_CACHE_LOGGING_DBG) {
|
||||
self.tile_cache_logger.serialize_updates(&updates);
|
||||
}
|
||||
}
|
||||
doc.data_stores.apply_updates(updates, &mut profile_counters);
|
||||
}
|
||||
|
||||
|
||||
// Build the hit tester while the APZ lock is held so that its content
|
||||
// is in sync with the gecko APZ tree.
|
||||
if !doc.hit_tester_is_valid {
|
||||
doc.rebuild_hit_tester();
|
||||
}
|
||||
if let Some(ref tx) = result_tx {
|
||||
let (resume_tx, resume_rx) = channel();
|
||||
tx.send(SceneSwapResult::Complete(resume_tx)).unwrap();
|
||||
// Block until the post-swap hook has completed on
|
||||
// the scene builder thread. We need to do this before
|
||||
// we can sample from the sampler hook which might happen
|
||||
// in the update_document call below.
|
||||
resume_rx.recv().ok();
|
||||
}
|
||||
} else {
|
||||
// The document was removed while we were building it, skip it.
|
||||
// TODO: we might want to just ensure that removed documents are
|
||||
// always forwarded to the scene builder thread to avoid this case.
|
||||
if let Some(ref tx) = result_tx {
|
||||
tx.send(SceneSwapResult::Aborted).unwrap();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
self.resource_cache.add_rasterized_blob_images(
|
||||
txn.rasterized_blobs.take(),
|
||||
&mut profile_counters.resources.texture_cache,
|
||||
);
|
||||
|
||||
self.update_document(
|
||||
txn.document_id,
|
||||
txn.resource_updates.take(),
|
||||
txn.frame_ops.take(),
|
||||
txn.notifications.take(),
|
||||
txn.render_frame,
|
||||
txn.invalidate_rendered_frame,
|
||||
&mut frame_counter,
|
||||
&mut profile_counters,
|
||||
has_built_scene,
|
||||
);
|
||||
}
|
||||
|
||||
let built_frame = self.process_transaction(
|
||||
txns,
|
||||
result_tx,
|
||||
&mut frame_counter,
|
||||
&mut profile_counters,
|
||||
);
|
||||
|
||||
if built_frame {
|
||||
self.save_capture_sequence();
|
||||
}
|
||||
|
||||
self.bookkeep_after_frames();
|
||||
},
|
||||
SceneBuilderResult::FlushComplete(tx) => {
|
||||
|
@ -1041,107 +1088,6 @@ impl RenderBackend {
|
|||
}
|
||||
}
|
||||
|
||||
fn process_transaction(
|
||||
&mut self,
|
||||
mut txns: Vec<Box<BuiltTransaction>>,
|
||||
result_tx: Option<Sender<SceneSwapResult>>,
|
||||
frame_counter: &mut u32,
|
||||
profile_counters: &mut BackendProfileCounters,
|
||||
) -> bool {
|
||||
self.prepare_for_frames();
|
||||
self.maybe_force_nop_documents(
|
||||
frame_counter,
|
||||
profile_counters,
|
||||
|document_id| txns.iter().any(|txn| txn.document_id == document_id));
|
||||
|
||||
let mut built_frame = false;
|
||||
for mut txn in txns.drain(..) {
|
||||
let has_built_scene = txn.built_scene.is_some();
|
||||
|
||||
if let Some(timings) = txn.timings {
|
||||
if has_built_scene {
|
||||
profile_counters.scene_changed = true;
|
||||
}
|
||||
|
||||
profile_counters.txn.set(
|
||||
timings.builder_start_time_ns,
|
||||
timings.builder_end_time_ns,
|
||||
timings.send_time_ns,
|
||||
timings.scene_build_start_time_ns,
|
||||
timings.scene_build_end_time_ns,
|
||||
timings.display_list_len,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(doc) = self.documents.get_mut(&txn.document_id) {
|
||||
doc.removed_pipelines.append(&mut txn.removed_pipelines);
|
||||
|
||||
if let Some(built_scene) = txn.built_scene.take() {
|
||||
doc.new_async_scene_ready(
|
||||
built_scene,
|
||||
&mut self.recycler,
|
||||
);
|
||||
}
|
||||
|
||||
// If there are any additions or removals of clip modes
|
||||
// during the scene build, apply them to the data store now.
|
||||
// This needs to happen before we build the hit tester.
|
||||
if let Some(updates) = txn.interner_updates.take() {
|
||||
#[cfg(feature = "capture")]
|
||||
{
|
||||
if self.debug_flags.contains(DebugFlags::TILE_CACHE_LOGGING_DBG) {
|
||||
self.tile_cache_logger.serialize_updates(&updates);
|
||||
}
|
||||
}
|
||||
doc.data_stores.apply_updates(updates, profile_counters);
|
||||
}
|
||||
|
||||
// Build the hit tester while the APZ lock is held so that its content
|
||||
// is in sync with the gecko APZ tree.
|
||||
if !doc.hit_tester_is_valid {
|
||||
doc.rebuild_hit_tester();
|
||||
}
|
||||
|
||||
if let Some(ref tx) = result_tx {
|
||||
let (resume_tx, resume_rx) = channel();
|
||||
tx.send(SceneSwapResult::Complete(resume_tx)).unwrap();
|
||||
// Block until the post-swap hook has completed on
|
||||
// the scene builder thread. We need to do this before
|
||||
// we can sample from the sampler hook which might happen
|
||||
// in the update_document call below.
|
||||
resume_rx.recv().ok();
|
||||
}
|
||||
} else {
|
||||
// The document was removed while we were building it, skip it.
|
||||
// TODO: we might want to just ensure that removed documents are
|
||||
// always forwarded to the scene builder thread to avoid this case.
|
||||
if let Some(ref tx) = result_tx {
|
||||
tx.send(SceneSwapResult::Aborted).unwrap();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
self.resource_cache.add_rasterized_blob_images(
|
||||
txn.rasterized_blobs.take(),
|
||||
&mut profile_counters.resources.texture_cache,
|
||||
);
|
||||
|
||||
built_frame |= self.update_document(
|
||||
txn.document_id,
|
||||
txn.resource_updates.take(),
|
||||
txn.frame_ops.take(),
|
||||
txn.notifications.take(),
|
||||
txn.render_frame,
|
||||
txn.invalidate_rendered_frame,
|
||||
frame_counter,
|
||||
profile_counters,
|
||||
has_built_scene,
|
||||
);
|
||||
}
|
||||
|
||||
built_frame
|
||||
}
|
||||
|
||||
fn process_api_msg(
|
||||
&mut self,
|
||||
msg: ApiMsg,
|
||||
|
@ -1272,28 +1218,12 @@ impl RenderBackend {
|
|||
let output = self.save_capture(root, bits, profile_counters);
|
||||
ResultMsg::DebugOutput(output)
|
||||
},
|
||||
#[cfg(feature = "capture")]
|
||||
DebugCommand::StartCaptureSequence(root, bits) => {
|
||||
self.start_capture_sequence(root, bits);
|
||||
return RenderBackendStatus::Continue;
|
||||
},
|
||||
#[cfg(feature = "capture")]
|
||||
DebugCommand::StopCaptureSequence => {
|
||||
self.stop_capture_sequence();
|
||||
return RenderBackendStatus::Continue;
|
||||
},
|
||||
#[cfg(feature = "replay")]
|
||||
DebugCommand::LoadCapture(path, ids, tx) => {
|
||||
DebugCommand::LoadCapture(root, tx) => {
|
||||
NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed);
|
||||
*frame_counter += 1;
|
||||
|
||||
let mut config = CaptureConfig::new(path, CaptureBits::all());
|
||||
if let Some((scene_id, frame_id)) = ids {
|
||||
config.scene_id = scene_id;
|
||||
config.frame_id = frame_id;
|
||||
}
|
||||
|
||||
self.load_capture(config, profile_counters);
|
||||
self.load_capture(&root, profile_counters);
|
||||
|
||||
for (id, doc) in &self.documents {
|
||||
let captured = CapturedDocument {
|
||||
|
@ -1536,9 +1466,8 @@ impl RenderBackend {
|
|||
profile_counters,
|
||||
|document_id| txns.iter().any(|txn| txn.document_id == document_id));
|
||||
|
||||
let mut built_frame = false;
|
||||
for mut txn in txns {
|
||||
built_frame |= self.update_document(
|
||||
self.update_document(
|
||||
txn.document_id,
|
||||
txn.resource_updates.take(),
|
||||
txn.frame_ops.take(),
|
||||
|
@ -1550,10 +1479,7 @@ impl RenderBackend {
|
|||
false
|
||||
);
|
||||
}
|
||||
if built_frame {
|
||||
#[cfg(feature = "capture")]
|
||||
self.save_capture_sequence();
|
||||
}
|
||||
|
||||
self.bookkeep_after_frames();
|
||||
return;
|
||||
}
|
||||
|
@ -1583,10 +1509,8 @@ impl RenderBackend {
|
|||
.cloned()
|
||||
.filter(|key| !document_already_present(*key))
|
||||
.collect();
|
||||
#[allow(unused_variables)]
|
||||
let mut built_frame = false;
|
||||
for &document_id in &nop_documents {
|
||||
built_frame |= self.update_document(
|
||||
self.update_document(
|
||||
document_id,
|
||||
Vec::default(),
|
||||
Vec::default(),
|
||||
|
@ -1597,11 +1521,6 @@ impl RenderBackend {
|
|||
profile_counters,
|
||||
false);
|
||||
}
|
||||
#[cfg(feature = "capture")]
|
||||
match built_frame {
|
||||
true => self.save_capture_sequence(),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1616,7 +1535,7 @@ impl RenderBackend {
|
|||
frame_counter: &mut u32,
|
||||
profile_counters: &mut BackendProfileCounters,
|
||||
has_built_scene: bool,
|
||||
) -> bool {
|
||||
) {
|
||||
let requested_frame = render_frame;
|
||||
|
||||
let requires_frame_build = self.requires_frame_build();
|
||||
|
@ -1738,26 +1657,6 @@ impl RenderBackend {
|
|||
}
|
||||
doc.prev_composite_descriptor = composite_descriptor;
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
match self.capture_config {
|
||||
Some(ref mut config) => {
|
||||
// FIXME(aosmond): document splitting causes multiple prepare frames
|
||||
config.prepare_frame();
|
||||
|
||||
if config.bits.contains(CaptureBits::FRAME) {
|
||||
let file_name = format!("frame-{}-{}", document_id.namespace_id.0, document_id.id);
|
||||
config.serialize_for_frame(&rendered_document.frame, file_name);
|
||||
}
|
||||
|
||||
let data_stores_name = format!("data-stores-{}-{}", document_id.namespace_id.0, document_id.id);
|
||||
config.serialize_for_frame(&doc.data_stores, data_stores_name);
|
||||
|
||||
let properties_name = format!("properties-{}-{}", document_id.namespace_id.0, document_id.id);
|
||||
config.serialize_for_frame(&doc.dynamic_properties, properties_name);
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
|
||||
let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
|
||||
self.result_tx.send(msg).unwrap();
|
||||
|
||||
|
@ -1805,8 +1704,6 @@ impl RenderBackend {
|
|||
if !doc.hit_tester_is_valid {
|
||||
doc.rebuild_hit_tester();
|
||||
}
|
||||
|
||||
build_frame
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "debugger"))]
|
||||
|
@ -1854,29 +1751,6 @@ impl RenderBackend {
|
|||
// thread waiting on the request.
|
||||
self.scene_tx.send(SceneBuilderRequest::ReportMemory(report, tx)).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn save_capture_sequence(&mut self) {
|
||||
if let Some(ref mut config) = self.capture_config {
|
||||
let deferred = self.resource_cache.save_capture_sequence(config);
|
||||
|
||||
let backend = PlainRenderBackend {
|
||||
default_device_pixel_ratio: self.default_device_pixel_ratio,
|
||||
frame_config: self.frame_config.clone(),
|
||||
resource_sequence_id: config.resource_id,
|
||||
documents: self.documents
|
||||
.iter()
|
||||
.map(|(id, doc)| (*id, doc.view.clone()))
|
||||
.collect(),
|
||||
};
|
||||
config.serialize_for_frame(&backend, "backend");
|
||||
|
||||
if !deferred.is_empty() {
|
||||
let msg = ResultMsg::DebugOutput(DebugOutput::SaveCapture(config.clone(), deferred));
|
||||
self.result_tx.send(msg).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_blob_image_updates(updates: &[ResourceUpdate]) -> Vec<BlobImageKey> {
|
||||
|
@ -1909,6 +1783,7 @@ impl RenderBackend {
|
|||
profile_counters: &mut BackendProfileCounters,
|
||||
) -> DebugOutput {
|
||||
use std::fs;
|
||||
use crate::capture::CaptureConfig;
|
||||
use crate::render_task_graph::dump_render_tasks_as_svg;
|
||||
|
||||
debug!("capture: saving {:?}", root);
|
||||
|
@ -1942,17 +1817,19 @@ impl RenderBackend {
|
|||
// it has `pipeline_epoch_map`,
|
||||
// which may capture necessary details for some cases.
|
||||
let file_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&rendered_document.frame, file_name);
|
||||
config.serialize(&rendered_document.frame, file_name);
|
||||
let file_name = format!("spatial-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_tree_for_frame(&doc.scene.spatial_tree, file_name);
|
||||
config.serialize_tree(&doc.scene.spatial_tree, file_name);
|
||||
let file_name = format!("built-primitives-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&doc.scene.prim_store, file_name);
|
||||
config.serialize(&doc.scene.prim_store, file_name);
|
||||
let file_name = format!("built-clips-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&doc.scene.clip_store, file_name);
|
||||
config.serialize(&doc.scene.clip_store, file_name);
|
||||
let file_name = format!("scratch-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&doc.scratch, file_name);
|
||||
config.serialize(&doc.scratch, file_name);
|
||||
let file_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize(&doc.dynamic_properties, file_name);
|
||||
let file_name = format!("render-tasks-{}-{}.svg", id.namespace_id.0, id.id);
|
||||
let mut svg_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
|
||||
let mut svg_file = fs::File::create(&config.file_path(file_name, "svg"))
|
||||
.expect("Failed to open the SVG file.");
|
||||
dump_render_tasks_as_svg(
|
||||
&rendered_document.frame.render_tasks,
|
||||
|
@ -1962,10 +1839,7 @@ impl RenderBackend {
|
|||
}
|
||||
|
||||
let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&doc.data_stores, data_stores_name);
|
||||
|
||||
let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_frame(&doc.dynamic_properties, properties_name);
|
||||
config.serialize(&doc.data_stores, data_stores_name);
|
||||
}
|
||||
|
||||
if config.bits.contains(CaptureBits::FRAME) {
|
||||
|
@ -1991,15 +1865,14 @@ impl RenderBackend {
|
|||
let backend = PlainRenderBackend {
|
||||
default_device_pixel_ratio: self.default_device_pixel_ratio,
|
||||
frame_config: self.frame_config.clone(),
|
||||
resource_sequence_id: 0,
|
||||
documents: self.documents
|
||||
.iter()
|
||||
.map(|(id, doc)| (*id, doc.view.clone()))
|
||||
.collect(),
|
||||
resources,
|
||||
};
|
||||
|
||||
config.serialize_for_frame(&backend, "backend");
|
||||
config.serialize_for_frame(&resources, "plain-resources");
|
||||
config.serialize(&backend, "backend");
|
||||
|
||||
if config.bits.contains(CaptureBits::FRAME) {
|
||||
let msg_update_resources = ResultMsg::UpdateResources {
|
||||
|
@ -2010,86 +1883,47 @@ impl RenderBackend {
|
|||
// Save the texture/glyph/image caches.
|
||||
info!("\tresource cache");
|
||||
let caches = self.resource_cache.save_caches(&config.root);
|
||||
config.serialize_for_resource(&caches, "resource_cache");
|
||||
config.serialize(&caches, "resource_cache");
|
||||
info!("\tgpu cache");
|
||||
config.serialize_for_resource(&self.gpu_cache, "gpu_cache");
|
||||
config.serialize(&self.gpu_cache, "gpu_cache");
|
||||
}
|
||||
|
||||
DebugOutput::SaveCapture(config, deferred)
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn start_capture_sequence(
|
||||
&mut self,
|
||||
root: PathBuf,
|
||||
bits: CaptureBits,
|
||||
) {
|
||||
self.scene_tx.send(SceneBuilderRequest::StartCaptureSequence(CaptureConfig::new(root, bits))).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn stop_capture_sequence(
|
||||
&mut self,
|
||||
) {
|
||||
self.scene_tx.send(SceneBuilderRequest::StopCaptureSequence).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
fn load_capture(
|
||||
&mut self,
|
||||
mut config: CaptureConfig,
|
||||
root: &PathBuf,
|
||||
profile_counters: &mut BackendProfileCounters,
|
||||
) {
|
||||
debug!("capture: loading {:?}", config.frame_root());
|
||||
let backend = config.deserialize_for_frame::<PlainRenderBackend, _>("backend")
|
||||
use crate::capture::CaptureConfig;
|
||||
|
||||
debug!("capture: loading {:?}", root);
|
||||
let backend = CaptureConfig::deserialize::<PlainRenderBackend, _>(root, "backend")
|
||||
.expect("Unable to open backend.ron");
|
||||
let caches_maybe = CaptureConfig::deserialize::<PlainCacheOwn, _>(root, "resource_cache");
|
||||
|
||||
// If this is a capture sequence, then the ID will be non-zero, and won't
|
||||
// match what is loaded, but for still captures, the ID will be zero.
|
||||
let first_load = backend.resource_sequence_id == 0;
|
||||
if self.loaded_resource_sequence_id != backend.resource_sequence_id || first_load {
|
||||
// FIXME(aosmond): We clear the documents because when we update the
|
||||
// resource cache, we actually wipe and reload, because we don't
|
||||
// know what is the same and what has changed. If we were to keep as
|
||||
// much of the resource cache state as possible, we could avoid
|
||||
// flushing the document state (which has its own dependecies on the
|
||||
// cache).
|
||||
//
|
||||
// FIXME(aosmond): If we try to load the next capture in the
|
||||
// sequence too quickly, we may lose resources we depend on in the
|
||||
// current frame. This can cause panics. Ideally we would not
|
||||
// advance to the next frame until the FrameRendered event for all
|
||||
// of the pipelines.
|
||||
self.documents.clear();
|
||||
// Note: it would be great to have `RenderBackend` to be split
|
||||
// rather explicitly on what's used before and after scene building
|
||||
// so that, for example, we never miss anything in the code below:
|
||||
|
||||
config.resource_id = backend.resource_sequence_id;
|
||||
self.loaded_resource_sequence_id = backend.resource_sequence_id;
|
||||
let plain_externals = self.resource_cache.load_capture(
|
||||
backend.resources,
|
||||
caches_maybe,
|
||||
root,
|
||||
);
|
||||
let msg_load = ResultMsg::DebugOutput(
|
||||
DebugOutput::LoadCapture(root.clone(), plain_externals)
|
||||
);
|
||||
self.result_tx.send(msg_load).unwrap();
|
||||
|
||||
let plain_resources = config.deserialize_for_resource::<PlainResources, _>("plain-resources")
|
||||
.expect("Unable to open plain-resources.ron");
|
||||
let caches_maybe = config.deserialize_for_resource::<PlainCacheOwn, _>("resource_cache");
|
||||
|
||||
// Note: it would be great to have `RenderBackend` to be split
|
||||
// rather explicitly on what's used before and after scene building
|
||||
// so that, for example, we never miss anything in the code below:
|
||||
|
||||
let plain_externals = self.resource_cache.load_capture(
|
||||
plain_resources,
|
||||
caches_maybe,
|
||||
&config,
|
||||
);
|
||||
|
||||
let msg_load = ResultMsg::DebugOutput(
|
||||
DebugOutput::LoadCapture(config.clone(), plain_externals)
|
||||
);
|
||||
self.result_tx.send(msg_load).unwrap();
|
||||
|
||||
self.gpu_cache = match config.deserialize_for_resource::<GpuCache, _>("gpu_cache") {
|
||||
Some(gpu_cache) => gpu_cache,
|
||||
None => GpuCache::new(),
|
||||
};
|
||||
}
|
||||
self.gpu_cache = match CaptureConfig::deserialize::<GpuCache, _>(root, "gpu_cache") {
|
||||
Some(gpu_cache) => gpu_cache,
|
||||
None => GpuCache::new(),
|
||||
};
|
||||
|
||||
self.documents.clear();
|
||||
self.default_device_pixel_ratio = backend.default_device_pixel_ratio;
|
||||
self.frame_config = backend.frame_config;
|
||||
|
||||
|
@ -2098,64 +1932,41 @@ impl RenderBackend {
|
|||
for (id, view) in backend.documents {
|
||||
debug!("\tdocument {:?}", id);
|
||||
let scene_name = format!("scene-{}-{}", id.namespace_id.0, id.id);
|
||||
let scene = config.deserialize_for_scene::<Scene, _>(&scene_name)
|
||||
let scene = CaptureConfig::deserialize::<Scene, _>(root, &scene_name)
|
||||
.expect(&format!("Unable to open {}.ron", scene_name));
|
||||
|
||||
let interners_name = format!("interners-{}-{}", id.namespace_id.0, id.id);
|
||||
let interners = config.deserialize_for_scene::<Interners, _>(&interners_name)
|
||||
let interners = CaptureConfig::deserialize::<Interners, _>(root, &interners_name)
|
||||
.expect(&format!("Unable to open {}.ron", interners_name));
|
||||
|
||||
let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
|
||||
let data_stores = config.deserialize_for_frame::<DataStores, _>(&data_stores_name)
|
||||
let data_stores = CaptureConfig::deserialize::<DataStores, _>(root, &data_stores_name)
|
||||
.expect(&format!("Unable to open {}.ron", data_stores_name));
|
||||
|
||||
let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
|
||||
let properties = config.deserialize_for_frame::<SceneProperties, _>(&properties_name)
|
||||
.expect(&format!("Unable to open {}.ron", properties_name));
|
||||
|
||||
// Update the document if it still exists, rather than replace it entirely.
|
||||
// This allows us to preserve state information such as the frame stamp,
|
||||
// which is necessary for cache sanity.
|
||||
match self.documents.entry(id) {
|
||||
Occupied(entry) => {
|
||||
let doc = entry.into_mut();
|
||||
doc.view = view.clone();
|
||||
doc.loaded_scene = scene.clone();
|
||||
doc.data_stores = data_stores;
|
||||
doc.dynamic_properties = properties;
|
||||
doc.frame_is_valid = false;
|
||||
doc.rendered_frame_is_valid = false;
|
||||
doc.has_built_scene = false;
|
||||
doc.hit_tester_is_valid = false;
|
||||
}
|
||||
Vacant(entry) => {
|
||||
let doc = Document {
|
||||
id,
|
||||
scene: BuiltScene::empty(),
|
||||
removed_pipelines: Vec::new(),
|
||||
view: view.clone(),
|
||||
stamp: FrameStamp::first(id),
|
||||
frame_builder: FrameBuilder::new(),
|
||||
output_pipelines: FastHashSet::default(),
|
||||
dynamic_properties: properties,
|
||||
hit_tester: None,
|
||||
shared_hit_tester: Arc::new(SharedHitTester::new()),
|
||||
frame_is_valid: false,
|
||||
hit_tester_is_valid: false,
|
||||
rendered_frame_is_valid: false,
|
||||
has_built_scene: false,
|
||||
data_stores,
|
||||
scratch: PrimitiveScratchBuffer::new(),
|
||||
render_task_counters: RenderTaskGraphCounters::new(),
|
||||
loaded_scene: scene.clone(),
|
||||
prev_composite_descriptor: CompositeDescriptor::empty(),
|
||||
};
|
||||
entry.insert(doc);
|
||||
}
|
||||
let doc = Document {
|
||||
id,
|
||||
scene: BuiltScene::empty(),
|
||||
removed_pipelines: Vec::new(),
|
||||
view: view.clone(),
|
||||
stamp: FrameStamp::first(id),
|
||||
frame_builder: FrameBuilder::new(),
|
||||
output_pipelines: FastHashSet::default(),
|
||||
dynamic_properties: SceneProperties::new(),
|
||||
hit_tester: None,
|
||||
shared_hit_tester: Arc::new(SharedHitTester::new()),
|
||||
frame_is_valid: false,
|
||||
hit_tester_is_valid: false,
|
||||
rendered_frame_is_valid: false,
|
||||
has_built_scene: false,
|
||||
data_stores,
|
||||
scratch: PrimitiveScratchBuffer::new(),
|
||||
render_task_counters: RenderTaskGraphCounters::new(),
|
||||
loaded_scene: scene.clone(),
|
||||
prev_composite_descriptor: CompositeDescriptor::empty(),
|
||||
};
|
||||
|
||||
let frame_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
|
||||
let frame = config.deserialize_for_frame::<Frame, _>(frame_name);
|
||||
let frame = CaptureConfig::deserialize::<Frame, _>(root, frame_name);
|
||||
let build_frame = match frame {
|
||||
Some(frame) => {
|
||||
info!("\tloaded a built frame with {} passes", frame.passes.len());
|
||||
|
@ -2186,11 +1997,13 @@ impl RenderBackend {
|
|||
scene,
|
||||
view: view.clone(),
|
||||
config: self.frame_config.clone(),
|
||||
output_pipelines: self.documents[&id].output_pipelines.clone(),
|
||||
output_pipelines: doc.output_pipelines.clone(),
|
||||
font_instances: self.resource_cache.get_font_instances(),
|
||||
build_frame,
|
||||
interners,
|
||||
});
|
||||
|
||||
self.documents.insert(id, doc);
|
||||
}
|
||||
|
||||
if !scenes_to_build.is_empty() {
|
||||
|
|
|
@ -2890,9 +2890,9 @@ impl Renderer {
|
|||
self.save_capture(config, deferred);
|
||||
}
|
||||
#[cfg(feature = "replay")]
|
||||
DebugOutput::LoadCapture(config, plain_externals) => {
|
||||
DebugOutput::LoadCapture(root, plain_externals) => {
|
||||
self.active_documents.clear();
|
||||
self.load_capture(config, plain_externals);
|
||||
self.load_capture(root, plain_externals);
|
||||
}
|
||||
},
|
||||
ResultMsg::DebugCommand(command) => {
|
||||
|
@ -3132,9 +3132,7 @@ impl Renderer {
|
|||
self.debug_server.send(json);
|
||||
}
|
||||
DebugCommand::SaveCapture(..) |
|
||||
DebugCommand::LoadCapture(..) |
|
||||
DebugCommand::StartCaptureSequence(..) |
|
||||
DebugCommand::StopCaptureSequence => {
|
||||
DebugCommand::LoadCapture(..) => {
|
||||
panic!("Capture commands are not welcome here! Did you build with 'capture' feature?")
|
||||
}
|
||||
DebugCommand::ClearCaches(_)
|
||||
|
@ -6929,13 +6927,7 @@ struct PlainRenderer {
|
|||
gpu_cache: PlainTexture,
|
||||
gpu_cache_frame_id: FrameId,
|
||||
textures: FastHashMap<CacheTextureId, PlainTexture>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
struct PlainExternalResources {
|
||||
images: Vec<ExternalCaptureImage>
|
||||
external_images: Vec<ExternalCaptureImage>
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
|
@ -7083,13 +7075,11 @@ impl Renderer {
|
|||
use std::io::Write;
|
||||
use api::{CaptureBits, ExternalImageData};
|
||||
|
||||
let root = config.resource_root();
|
||||
|
||||
self.device.begin_frame();
|
||||
let _gm = self.gpu_profile.start_marker("read GPU data");
|
||||
self.device.bind_read_target_impl(self.read_fbo);
|
||||
|
||||
if config.bits.contains(CaptureBits::EXTERNAL_RESOURCES) && !deferred_images.is_empty() {
|
||||
if !deferred_images.is_empty() {
|
||||
info!("saving external images");
|
||||
let mut arc_map = FastHashMap::<*const u8, String>::default();
|
||||
let mut tex_map = FastHashMap::<u32, String>::default();
|
||||
|
@ -7140,13 +7130,13 @@ impl Renderer {
|
|||
}
|
||||
};
|
||||
if let Some(bytes) = data {
|
||||
fs::File::create(root.join(&short_path))
|
||||
fs::File::create(config.root.join(&short_path))
|
||||
.expect(&format!("Unable to create {}", short_path))
|
||||
.write_all(&bytes)
|
||||
.unwrap();
|
||||
#[cfg(feature = "png")]
|
||||
CaptureConfig::save_png(
|
||||
root.join(&short_path).with_extension("png"),
|
||||
config.root.join(&short_path).with_extension("png"),
|
||||
def.descriptor.size,
|
||||
def.descriptor.format,
|
||||
def.descriptor.stride,
|
||||
|
@ -7158,19 +7148,15 @@ impl Renderer {
|
|||
external: def.external,
|
||||
uv: ext_image.uv,
|
||||
};
|
||||
config.serialize_for_resource(&plain, &def.short_path);
|
||||
config.serialize(&plain, &def.short_path);
|
||||
}
|
||||
for def in &deferred_images {
|
||||
handler.unlock(def.external.id, def.external.channel_index);
|
||||
}
|
||||
let plain_external = PlainExternalResources {
|
||||
images: deferred_images,
|
||||
};
|
||||
config.serialize_for_resource(&plain_external, "external_resources");
|
||||
}
|
||||
|
||||
if config.bits.contains(CaptureBits::FRAME) {
|
||||
let path_textures = root.join("textures");
|
||||
let path_textures = config.root.join("textures");
|
||||
if !path_textures.is_dir() {
|
||||
fs::create_dir(&path_textures).unwrap();
|
||||
}
|
||||
|
@ -7181,21 +7167,22 @@ impl Renderer {
|
|||
device_size: self.device_size,
|
||||
gpu_cache: Self::save_texture(
|
||||
&self.gpu_cache_texture.texture.as_ref().unwrap(),
|
||||
"gpu", &root, &mut self.device,
|
||||
"gpu", &config.root, &mut self.device,
|
||||
),
|
||||
gpu_cache_frame_id: self.gpu_cache_frame_id,
|
||||
textures: FastHashMap::default(),
|
||||
external_images: deferred_images,
|
||||
};
|
||||
|
||||
info!("saving cached textures");
|
||||
for (id, texture) in &self.texture_resolver.texture_cache_map {
|
||||
let file_name = format!("cache-{}", plain_self.textures.len() + 1);
|
||||
info!("\t{}", file_name);
|
||||
let plain = Self::save_texture(texture, &file_name, &root, &mut self.device);
|
||||
let plain = Self::save_texture(texture, &file_name, &config.root, &mut self.device);
|
||||
plain_self.textures.insert(*id, plain);
|
||||
}
|
||||
|
||||
config.serialize_for_resource(&plain_self, "renderer");
|
||||
config.serialize(&plain_self, "renderer");
|
||||
}
|
||||
|
||||
self.device.reset_read_target();
|
||||
|
@ -7205,9 +7192,7 @@ impl Renderer {
|
|||
|
||||
#[cfg(feature = "replay")]
|
||||
fn load_capture(
|
||||
&mut self,
|
||||
config: CaptureConfig,
|
||||
plain_externals: Vec<PlainExternalImage>,
|
||||
&mut self, root: PathBuf, plain_externals: Vec<PlainExternalImage>
|
||||
) {
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
@ -7220,8 +7205,6 @@ impl Renderer {
|
|||
data: FastHashMap::default(),
|
||||
};
|
||||
|
||||
let root = config.resource_root();
|
||||
|
||||
// Note: this is a `SCENE` level population of the external image handlers
|
||||
// It would put both external buffers and texture into the map.
|
||||
// But latter are going to be overwritten later in this function
|
||||
|
@ -7243,49 +7226,7 @@ impl Renderer {
|
|||
image_handler.data.insert((ext.id, ext.channel_index), value);
|
||||
}
|
||||
|
||||
if let Some(external_resources) = config.deserialize_for_resource::<PlainExternalResources, _>("external_resources") {
|
||||
info!("loading external texture-backed images");
|
||||
let mut native_map = FastHashMap::<String, gl::GLuint>::default();
|
||||
for ExternalCaptureImage { short_path, external, descriptor } in external_resources.images {
|
||||
let target = match external.image_type {
|
||||
ExternalImageType::TextureHandle(target) => target,
|
||||
ExternalImageType::Buffer => continue,
|
||||
};
|
||||
let plain_ext = config.deserialize_for_resource::<PlainExternalImage, _>(&short_path)
|
||||
.expect(&format!("Unable to read {}.ron", short_path));
|
||||
let key = (external.id, external.channel_index);
|
||||
|
||||
let tid = match native_map.entry(plain_ext.data) {
|
||||
Entry::Occupied(e) => e.get().clone(),
|
||||
Entry::Vacant(e) => {
|
||||
//TODO: provide a way to query both the layer count and the filter from external images
|
||||
let (layer_count, filter) = (1, TextureFilter::Linear);
|
||||
let plain_tex = PlainTexture {
|
||||
data: e.key().clone(),
|
||||
size: (descriptor.size, layer_count),
|
||||
format: descriptor.format,
|
||||
filter,
|
||||
has_depth: false,
|
||||
};
|
||||
let t = Self::load_texture(
|
||||
target,
|
||||
&plain_tex,
|
||||
None,
|
||||
&root,
|
||||
&mut self.device
|
||||
);
|
||||
let extex = t.0.into_external();
|
||||
self.owned_external_images.insert(key, extex.clone());
|
||||
e.insert(extex.internal_id()).clone()
|
||||
}
|
||||
};
|
||||
|
||||
let value = (CapturedExternalImageData::NativeTexture(tid), plain_ext.uv);
|
||||
image_handler.data.insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(renderer) = config.deserialize_for_resource::<PlainRenderer, _>("renderer") {
|
||||
if let Some(renderer) = CaptureConfig::deserialize::<PlainRenderer, _>(&root, "renderer") {
|
||||
info!("loading cached textures");
|
||||
self.device_size = renderer.device_size;
|
||||
self.device.begin_frame();
|
||||
|
@ -7339,18 +7280,46 @@ impl Renderer {
|
|||
}
|
||||
self.gpu_cache_frame_id = renderer.gpu_cache_frame_id;
|
||||
|
||||
self.device.end_frame();
|
||||
} else {
|
||||
info!("loading cached textures");
|
||||
self.device.begin_frame();
|
||||
for (_id, texture) in self.texture_resolver.texture_cache_map.drain() {
|
||||
self.device.delete_texture(texture);
|
||||
info!("loading external texture-backed images");
|
||||
let mut native_map = FastHashMap::<String, gl::GLuint>::default();
|
||||
for ExternalCaptureImage { short_path, external, descriptor } in renderer.external_images {
|
||||
let target = match external.image_type {
|
||||
ExternalImageType::TextureHandle(target) => target,
|
||||
ExternalImageType::Buffer => continue,
|
||||
};
|
||||
let plain_ext = CaptureConfig::deserialize::<PlainExternalImage, _>(&root, &short_path)
|
||||
.expect(&format!("Unable to read {}.ron", short_path));
|
||||
let key = (external.id, external.channel_index);
|
||||
|
||||
let tid = match native_map.entry(plain_ext.data) {
|
||||
Entry::Occupied(e) => e.get().clone(),
|
||||
Entry::Vacant(e) => {
|
||||
//TODO: provide a way to query both the layer count and the filter from external images
|
||||
let (layer_count, filter) = (1, TextureFilter::Linear);
|
||||
let plain_tex = PlainTexture {
|
||||
data: e.key().clone(),
|
||||
size: (descriptor.size, layer_count),
|
||||
format: descriptor.format,
|
||||
filter,
|
||||
has_depth: false,
|
||||
};
|
||||
let t = Self::load_texture(
|
||||
target,
|
||||
&plain_tex,
|
||||
None,
|
||||
&root,
|
||||
&mut self.device
|
||||
);
|
||||
let extex = t.0.into_external();
|
||||
self.owned_external_images.insert(key, extex.clone());
|
||||
e.insert(extex.internal_id()).clone()
|
||||
}
|
||||
};
|
||||
|
||||
let value = (CapturedExternalImageData::NativeTexture(tid), plain_ext.uv);
|
||||
image_handler.data.insert(key, value);
|
||||
}
|
||||
|
||||
info!("loading gpu cache");
|
||||
if let Some(t) = self.gpu_cache_texture.texture.take() {
|
||||
self.device.delete_texture(t);
|
||||
}
|
||||
self.device.end_frame();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use api::units::*;
|
|||
use crate::capture::ExternalCaptureImage;
|
||||
#[cfg(feature = "replay")]
|
||||
use crate::capture::PlainExternalImage;
|
||||
#[cfg(any(feature = "replay", feature = "png", feature="capture"))]
|
||||
#[cfg(any(feature = "replay", feature = "png"))]
|
||||
use crate::capture::CaptureConfig;
|
||||
use crate::composite::{NativeSurfaceId, NativeSurfaceOperation, NativeTileId, NativeSurfaceOperationDetails};
|
||||
use crate::device::TextureFilter;
|
||||
|
@ -459,12 +459,6 @@ pub struct ResourceCache {
|
|||
state: State,
|
||||
current_frame_id: FrameId,
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
/// Used for capture sequences. If the resource cache is updated, then we
|
||||
/// mark it as dirty. When the next frame is captured in the sequence, we
|
||||
/// dump the state of the resource cache.
|
||||
capture_dirty: bool,
|
||||
|
||||
pub texture_cache: TextureCache,
|
||||
|
||||
/// TODO(gw): We should expire (parts of) this cache semi-regularly!
|
||||
|
@ -512,8 +506,6 @@ impl ResourceCache {
|
|||
// We want to keep three frames worth of delete blob keys
|
||||
deleted_blob_keys: vec![Vec::new(), Vec::new(), Vec::new()].into(),
|
||||
pending_native_surface_updates: Vec::new(),
|
||||
#[cfg(feature = "capture")]
|
||||
capture_dirty: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,11 +568,6 @@ impl ResourceCache {
|
|||
// TODO, there is potential for optimization here, by processing updates in
|
||||
// bulk rather than one by one (for example by sorting allocations by size or
|
||||
// in a way that reduces fragmentation in the atlas).
|
||||
#[cfg(feature = "capture")]
|
||||
match updates.is_empty() {
|
||||
false => self.capture_dirty = true,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
for update in updates {
|
||||
match update {
|
||||
|
@ -646,12 +633,6 @@ impl ResourceCache {
|
|||
updates: &mut Vec<ResourceUpdate>,
|
||||
profile_counters: &mut ResourceProfileCounters,
|
||||
) {
|
||||
#[cfg(feature = "capture")]
|
||||
match updates.is_empty() {
|
||||
false => self.capture_dirty = true,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
for update in updates.iter() {
|
||||
match *update {
|
||||
ResourceUpdate::AddBlobImage(ref img) => {
|
||||
|
@ -2017,7 +1998,7 @@ impl ResourceCache {
|
|||
&mut self,
|
||||
resources: PlainResources,
|
||||
caches: Option<PlainCacheOwn>,
|
||||
config: &CaptureConfig,
|
||||
root: &PathBuf,
|
||||
) -> Vec<PlainExternalImage> {
|
||||
use std::{fs, path::Path};
|
||||
|
||||
|
@ -2059,7 +2040,6 @@ impl ResourceCache {
|
|||
res.image_templates.images.clear();
|
||||
|
||||
info!("\tfont templates...");
|
||||
let root = config.resource_root();
|
||||
let native_font_replacement = Arc::new(NATIVE_FONT.to_vec());
|
||||
for (key, plain_template) in resources.font_templates {
|
||||
let arc = match raw_map.entry(plain_template.data) {
|
||||
|
@ -2091,7 +2071,7 @@ impl ResourceCache {
|
|||
info!("\timage templates...");
|
||||
let mut external_images = Vec::new();
|
||||
for (key, template) in resources.image_templates {
|
||||
let data = match config.deserialize_for_resource::<PlainExternalImage, _>(&template.data) {
|
||||
let data = match CaptureConfig::deserialize::<PlainExternalImage, _>(root, &template.data) {
|
||||
Some(plain) => {
|
||||
let ext_data = plain.external;
|
||||
external_images.push(plain);
|
||||
|
@ -2124,19 +2104,6 @@ impl ResourceCache {
|
|||
|
||||
external_images
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
pub fn save_capture_sequence(&mut self, config: &mut CaptureConfig) -> Vec<ExternalCaptureImage> {
|
||||
if self.capture_dirty {
|
||||
self.capture_dirty = false;
|
||||
config.prepare_resource();
|
||||
let (resources, deferred) = self.save_capture(&config.resource_root());
|
||||
config.serialize_for_resource(&resources, "plain-resources.ron");
|
||||
deferred
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For now the blob's coordinate space have the same pixel sizes as the
|
||||
|
|
|
@ -7,7 +7,7 @@ use api::{DocumentId, PipelineId, ApiMsg, FrameMsg, ResourceUpdate, ExternalEven
|
|||
use api::{BuiltDisplayList, ColorF, NotificationRequest, Checkpoint, IdNamespace};
|
||||
use api::{ClipIntern, FilterDataIntern, MemoryReport, PrimitiveKeyKind};
|
||||
use api::units::LayoutSize;
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
#[cfg(feature = "capture")]
|
||||
use crate::capture::CaptureConfig;
|
||||
use crate::frame_builder::FrameBuilderConfig;
|
||||
use crate::scene_building::SceneBuilder;
|
||||
|
@ -161,18 +161,12 @@ pub enum SceneBuilderRequest {
|
|||
SaveScene(CaptureConfig),
|
||||
#[cfg(feature = "replay")]
|
||||
LoadScenes(Vec<LoadScene>),
|
||||
#[cfg(feature = "capture")]
|
||||
StartCaptureSequence(CaptureConfig),
|
||||
#[cfg(feature = "capture")]
|
||||
StopCaptureSequence,
|
||||
DocumentsForDebugger
|
||||
}
|
||||
|
||||
// Message from scene builder to render backend.
|
||||
pub enum SceneBuilderResult {
|
||||
Transactions(Vec<Box<BuiltTransaction>>, Option<Sender<SceneSwapResult>>),
|
||||
#[cfg(feature = "capture")]
|
||||
CapturedTransactions(Vec<Box<BuiltTransaction>>, CaptureConfig, Option<Sender<SceneSwapResult>>),
|
||||
ExternalEvent(ExternalEvent),
|
||||
FlushComplete(Sender<()>),
|
||||
ClearNamespace(IdNamespace),
|
||||
|
@ -273,9 +267,7 @@ pub struct SceneBuilderThread {
|
|||
size_of_ops: Option<MallocSizeOfOps>,
|
||||
hooks: Option<Box<dyn SceneBuilderHooks + Send>>,
|
||||
simulate_slow_ms: u32,
|
||||
removed_pipelines: FastHashSet<PipelineId>,
|
||||
#[cfg(feature = "capture")]
|
||||
capture_config: Option<CaptureConfig>,
|
||||
removed_pipelines: FastHashSet<PipelineId>
|
||||
}
|
||||
|
||||
pub struct SceneBuilderThreadChannels {
|
||||
|
@ -321,8 +313,6 @@ impl SceneBuilderThread {
|
|||
hooks,
|
||||
simulate_slow_ms: 0,
|
||||
removed_pipelines: FastHashSet::default(),
|
||||
#[cfg(feature = "capture")]
|
||||
capture_config: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,11 +343,6 @@ impl SceneBuilderThread {
|
|||
let built_txns : Vec<Box<BuiltTransaction>> = txns.iter_mut()
|
||||
.map(|txn| self.process_transaction(txn))
|
||||
.collect();
|
||||
#[cfg(feature = "capture")]
|
||||
match built_txns.iter().any(|txn| txn.built_scene.is_some()) {
|
||||
true => self.save_capture_sequence(),
|
||||
_ => {},
|
||||
}
|
||||
self.forward_built_transactions(built_txns);
|
||||
}
|
||||
Ok(SceneBuilderRequest::DeleteDocument(document_id)) => {
|
||||
|
@ -378,16 +363,6 @@ impl SceneBuilderThread {
|
|||
Ok(SceneBuilderRequest::SaveScene(config)) => {
|
||||
self.save_scene(config);
|
||||
}
|
||||
#[cfg(feature = "capture")]
|
||||
Ok(SceneBuilderRequest::StartCaptureSequence(config)) => {
|
||||
self.start_capture_sequence(config);
|
||||
}
|
||||
#[cfg(feature = "capture")]
|
||||
Ok(SceneBuilderRequest::StopCaptureSequence) => {
|
||||
// FIXME(aosmond): clear config for frames and resource cache without scene
|
||||
// rebuild?
|
||||
self.capture_config = None;
|
||||
}
|
||||
Ok(SceneBuilderRequest::DocumentsForDebugger) => {
|
||||
let json = self.get_docs_for_debugger();
|
||||
self.send(SceneBuilderResult::DocumentsForDebugger(json));
|
||||
|
@ -431,11 +406,11 @@ impl SceneBuilderThread {
|
|||
fn save_scene(&mut self, config: CaptureConfig) {
|
||||
for (id, doc) in &self.documents {
|
||||
let interners_name = format!("interners-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_scene(&doc.interners, interners_name);
|
||||
config.serialize(&doc.interners, interners_name);
|
||||
|
||||
if config.bits.contains(api::CaptureBits::SCENE) {
|
||||
let file_name = format!("scene-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_scene(&doc.scene, file_name);
|
||||
config.serialize(&doc.scene, file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,33 +471,6 @@ impl SceneBuilderThread {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn save_capture_sequence(
|
||||
&mut self,
|
||||
) {
|
||||
if let Some(ref mut config) = self.capture_config {
|
||||
config.prepare_scene();
|
||||
for (id, doc) in &self.documents {
|
||||
let interners_name = format!("interners-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_scene(&doc.interners, interners_name);
|
||||
|
||||
if config.bits.contains(api::CaptureBits::SCENE) {
|
||||
let file_name = format!("scene-{}-{}", id.namespace_id.0, id.id);
|
||||
config.serialize_for_scene(&doc.scene, file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
fn start_capture_sequence(
|
||||
&mut self,
|
||||
config: CaptureConfig,
|
||||
) {
|
||||
self.capture_config = Some(config);
|
||||
self.save_capture_sequence();
|
||||
}
|
||||
|
||||
#[cfg(feature = "debugger")]
|
||||
fn traverse_items<'a>(
|
||||
&self,
|
||||
|
@ -740,13 +688,6 @@ impl SceneBuilderThread {
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
#[cfg(feature = "capture")]
|
||||
match self.capture_config {
|
||||
Some(ref config) => self.tx.send(SceneBuilderResult::CapturedTransactions(txns, config.clone(), result_tx)).unwrap(),
|
||||
None => self.tx.send(SceneBuilderResult::Transactions(txns, result_tx)).unwrap(),
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "capture"))]
|
||||
self.tx.send(SceneBuilderResult::Transactions(txns, result_tx)).unwrap();
|
||||
|
||||
let _ = self.api_tx.send(ApiMsg::WakeUp);
|
||||
|
|
|
@ -913,8 +913,6 @@ bitflags!{
|
|||
const FRAME = 0x2;
|
||||
///
|
||||
const TILE_CACHE = 0x4;
|
||||
///
|
||||
const EXTERNAL_RESOURCES = 0x8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -969,11 +967,7 @@ pub enum DebugCommand {
|
|||
SaveCapture(PathBuf, CaptureBits),
|
||||
/// Load a capture of all the documents state.
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
LoadCapture(PathBuf, Option<(u32, u32)>, Sender<CapturedDocument>),
|
||||
/// Start capturing a sequence of scene/frame changes.
|
||||
StartCaptureSequence(PathBuf, CaptureBits),
|
||||
/// Stop capturing a sequence of scene/frame changes.
|
||||
StopCaptureSequence,
|
||||
LoadCapture(PathBuf, Sender<CapturedDocument>),
|
||||
/// Clear cached resources, forcing them to be re-uploaded from templates.
|
||||
ClearCaches(ClearCache),
|
||||
/// Enable/disable native compositor usage
|
||||
|
@ -1738,13 +1732,13 @@ impl RenderApi {
|
|||
}
|
||||
|
||||
/// Load a capture of the current frame state for debugging.
|
||||
pub fn load_capture(&self, path: PathBuf, ids: Option<(u32, u32)>) -> Vec<CapturedDocument> {
|
||||
pub fn load_capture(&self, path: PathBuf) -> Vec<CapturedDocument> {
|
||||
// First flush the scene builder otherwise async scenes might clobber
|
||||
// the capture we are about to load.
|
||||
self.flush_scene_builder();
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, ids, tx));
|
||||
let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, tx));
|
||||
self.send_message(msg);
|
||||
|
||||
let mut documents = Vec::new();
|
||||
|
@ -1754,18 +1748,6 @@ impl RenderApi {
|
|||
documents
|
||||
}
|
||||
|
||||
/// Start capturing a sequence of frames.
|
||||
pub fn start_capture_sequence(&self, path: PathBuf, bits: CaptureBits) {
|
||||
let msg = ApiMsg::DebugCommand(DebugCommand::StartCaptureSequence(path, bits));
|
||||
self.send_message(msg);
|
||||
}
|
||||
|
||||
/// Stop capturing sequences of frames.
|
||||
pub fn stop_capture_sequence(&self) {
|
||||
let msg = ApiMsg::DebugCommand(DebugCommand::StopCaptureSequence);
|
||||
self.send_message(msg);
|
||||
}
|
||||
|
||||
/// Update the state of builtin debugging facilities.
|
||||
pub fn send_debug_cmd(&self, cmd: DebugCommand) {
|
||||
let msg = ApiMsg::DebugCommand(cmd);
|
||||
|
|
|
@ -143,16 +143,6 @@ subcommands:
|
|||
long: keyframes
|
||||
takes_value: true
|
||||
help: Provide a keyframes file, that can be used to animate the yaml input file
|
||||
- scene-id:
|
||||
short: s
|
||||
long: scene-id
|
||||
takes_value: true
|
||||
help: Select a starting scene sequence ID (YAML capture sequence only).
|
||||
- frame-id:
|
||||
short: f
|
||||
long: frame-id
|
||||
takes_value: true
|
||||
help: Select a starting frame sequence ID (YAML capture sequence only).
|
||||
- INPUT:
|
||||
help: The input YAML, binary recording, or capture directory
|
||||
required: true
|
||||
|
|
|
@ -54,7 +54,7 @@ use webrender::api::*;
|
|||
use webrender::api::units::*;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||
use winit::VirtualKeyCode;
|
||||
use crate::wrench::{CapturedSequence, Wrench, WrenchThing};
|
||||
use crate::wrench::{Wrench, WrenchThing};
|
||||
use crate::yaml_frame_reader::YamlFrameReader;
|
||||
|
||||
pub const PLATFORM_DEFAULT_FACE_NAME: &str = "Arial";
|
||||
|
@ -764,18 +764,13 @@ fn render<'a>(
|
|||
let input_path = subargs.value_of("INPUT").map(PathBuf::from).unwrap();
|
||||
|
||||
// If the input is a directory, we are looking at a capture.
|
||||
let mut thing = if input_path.join("scenes").as_path().is_dir() {
|
||||
let scene_id = subargs.value_of("scene-id").map(|z| z.parse::<u32>().unwrap());
|
||||
let frame_id = subargs.value_of("frame-id").map(|z| z.parse::<u32>().unwrap());
|
||||
Box::new(CapturedSequence::new(
|
||||
input_path,
|
||||
scene_id.unwrap_or(1),
|
||||
frame_id.unwrap_or(1),
|
||||
))
|
||||
} else if input_path.as_path().is_dir() {
|
||||
let mut documents = wrench.api.load_capture(input_path, None);
|
||||
let mut thing = if input_path.as_path().is_dir() {
|
||||
let mut documents = wrench.api.load_capture(input_path);
|
||||
println!("loaded {:?}", documents.iter().map(|cd| cd.document_id).collect::<Vec<_>>());
|
||||
let captured = documents.swap_remove(0);
|
||||
if let Some(fb_size) = wrench.renderer.device_size() {
|
||||
window.resize(fb_size);
|
||||
}
|
||||
wrench.document_id = captured.document_id;
|
||||
Box::new(captured) as Box<dyn WrenchThing>
|
||||
} else {
|
||||
|
@ -799,10 +794,6 @@ fn render<'a>(
|
|||
window.update(wrench);
|
||||
thing.do_frame(wrench);
|
||||
|
||||
if let Some(fb_size) = wrench.renderer.device_size() {
|
||||
window.resize(fb_size);
|
||||
}
|
||||
|
||||
let mut debug_flags = DebugFlags::empty();
|
||||
debug_flags.set(DebugFlags::DISABLE_BATCHING, no_batch);
|
||||
|
||||
|
|
|
@ -1288,7 +1288,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
// 4. load the first one
|
||||
|
||||
let mut documents = self.wrench.api.load_capture(path.into(), None);
|
||||
let mut documents = self.wrench.api.load_capture(path.into());
|
||||
let captured = documents.swap_remove(0);
|
||||
|
||||
// 5. render the built frame and compare
|
||||
|
|
|
@ -140,71 +140,6 @@ impl WrenchThing for CapturedDocument {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CapturedSequence {
|
||||
root: PathBuf,
|
||||
frame: usize,
|
||||
frame_set: Vec<(u32, u32)>,
|
||||
}
|
||||
|
||||
impl CapturedSequence {
|
||||
pub fn new(root: PathBuf, scene_start: u32, frame_start: u32) -> Self {
|
||||
// Build set of a scene and frame IDs.
|
||||
let mut scene = scene_start;
|
||||
let mut frame = frame_start;
|
||||
let mut frame_set = Vec::new();
|
||||
while Self::scene_root(&root, scene).as_path().is_dir() {
|
||||
while Self::frame_root(&root, scene, frame).as_path().is_dir() {
|
||||
frame_set.push((scene, frame));
|
||||
frame += 1;
|
||||
}
|
||||
scene += 1;
|
||||
frame = 1;
|
||||
}
|
||||
|
||||
assert!(!frame_set.is_empty());
|
||||
|
||||
Self {
|
||||
root,
|
||||
frame: 0,
|
||||
frame_set,
|
||||
}
|
||||
}
|
||||
|
||||
fn scene_root(root: &PathBuf, scene: u32) -> PathBuf {
|
||||
let path = format!("scenes/{:05}", scene);
|
||||
root.join(path)
|
||||
}
|
||||
|
||||
fn frame_root(root: &PathBuf, scene: u32, frame: u32) -> PathBuf {
|
||||
let path = format!("scenes/{:05}/frames/{:05}", scene, frame);
|
||||
root.join(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl WrenchThing for CapturedSequence {
|
||||
fn next_frame(&mut self) {
|
||||
if self.frame + 1 < self.frame_set.len() {
|
||||
self.frame += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_frame(&mut self) {
|
||||
if self.frame > 0 {
|
||||
self.frame -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn do_frame(&mut self, wrench: &mut Wrench) -> u32 {
|
||||
let mut documents = wrench.api.load_capture(self.root.clone(), Some(self.frame_set[self.frame]));
|
||||
println!("loaded {:?} from {:?}",
|
||||
documents.iter().map(|cd| cd.document_id).collect::<Vec<_>>(),
|
||||
self.frame_set[self.frame]);
|
||||
let captured = documents.swap_remove(0);
|
||||
wrench.document_id = captured.document_id;
|
||||
self.frame as u32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Wrench {
|
||||
window_size: DeviceIntSize,
|
||||
pub device_pixel_ratio: f32,
|
||||
|
|
Загрузка…
Ссылка в новой задаче