Backed out changeset 419be9960357 (bug 1561367) for causing wrench bustages CLOSED TREE

This commit is contained in:
Stefan Hindli 2020-04-20 17:22:53 +03:00
Родитель 86d843e1cc
Коммит 84357fecdc
23 изменённых файлов: 247 добавлений и 865 удалений

Просмотреть файл

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