mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-10-30 14:01:39 +00:00
Factor wgpu-subscriber into its own repo
This commit is contained in:
parent
096c57008f
commit
350637df40
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1648,6 +1648,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu-subscriber"
|
name = "wgpu-subscriber"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/gfx-rs/subscriber.git?rev=cdc9feb53f152f9c41905ed9efeff2c1ed214361#cdc9feb53f152f9c41905ed9efeff2c1ed214361"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parking_lot 0.11.0",
|
"parking_lot 0.11.0",
|
||||||
"thread-id",
|
"thread-id",
|
||||||
|
@ -3,6 +3,5 @@ members = [
|
|||||||
"dummy",
|
"dummy",
|
||||||
"player",
|
"player",
|
||||||
"wgpu-core",
|
"wgpu-core",
|
||||||
"wgpu-subscriber",
|
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
|
@ -13,7 +13,6 @@ The implementation consists of the following parts:
|
|||||||
|
|
||||||
- [![Crates.io](https://img.shields.io/crates/v/wgpu-core.svg?label=wgpu-core)](https://crates.io/crates/wgpu-core) [![docs.rs](https://docs.rs/wgpu-core/badge.svg)](https://docs.rs/wgpu-core/) - internal Rust API for WebGPU implementations to use
|
- [![Crates.io](https://img.shields.io/crates/v/wgpu-core.svg?label=wgpu-core)](https://crates.io/crates/wgpu-core) [![docs.rs](https://docs.rs/wgpu-core/badge.svg)](https://docs.rs/wgpu-core/) - internal Rust API for WebGPU implementations to use
|
||||||
- [![Crates.io](https://img.shields.io/crates/v/wgpu-types.svg?label=wgpu-types)](https://crates.io/crates/wgpu-types) [![docs.rs](https://docs.rs/wgpu-types/badge.svg)](https://docs.rs/wgpu-types/) - Rust types shared between `wgpu-core`, `wgpu-native`, and `wgpu-rs`
|
- [![Crates.io](https://img.shields.io/crates/v/wgpu-types.svg?label=wgpu-types)](https://crates.io/crates/wgpu-types) [![docs.rs](https://docs.rs/wgpu-types/badge.svg)](https://docs.rs/wgpu-types/) - Rust types shared between `wgpu-core`, `wgpu-native`, and `wgpu-rs`
|
||||||
- [![Crates.io](https://img.shields.io/crates/v/wgpu-subscriber.svg?label=wgpu-subsciber)](https://crates.io/crates/wgpu-subscriber) [![docs.rs](https://docs.rs/wgpu-subscriber/badge.svg)](https://docs.rs/wgpu-subscriber/) - tracing subscribers to use with `wgpu`
|
|
||||||
- `player` - standalone application for replaying the API traces, uses `winit`
|
- `player` - standalone application for replaying the API traces, uses `winit`
|
||||||
|
|
||||||
This repository contains the core of `wgpu`, and is not usable directly by applications.
|
This repository contains the core of `wgpu`, and is not usable directly by applications.
|
||||||
|
@ -35,7 +35,8 @@ version = "0.5"
|
|||||||
features = ["replay", "raw-window-handle"]
|
features = ["replay", "raw-window-handle"]
|
||||||
|
|
||||||
[dependencies.wgpu-subscriber]
|
[dependencies.wgpu-subscriber]
|
||||||
path = "../wgpu-subscriber"
|
git = "https://github.com/gfx-rs/subscriber.git"
|
||||||
|
rev = "cdc9feb53f152f9c41905ed9efeff2c1ed214361"
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
[target.'cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies]
|
[target.'cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies]
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "wgpu-subscriber"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["wgpu developers"]
|
|
||||||
edition = "2018"
|
|
||||||
description = "WebGPU tracing subscriber"
|
|
||||||
homepage = "https://github.com/gfx-rs/wgpu"
|
|
||||||
repository = "https://github.com/gfx-rs/wgpu"
|
|
||||||
keywords = ["graphics"]
|
|
||||||
license = "MPL-2.0"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
|
|
||||||
[features]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
parking_lot = "0.11"
|
|
||||||
thread-id = "3"
|
|
||||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
|
||||||
tracing-log = "0.1"
|
|
||||||
tracing-subscriber = "0.2"
|
|
@ -1,172 +0,0 @@
|
|||||||
use crate::CURRENT_THREAD_ID;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use std::{
|
|
||||||
borrow::Cow,
|
|
||||||
fmt,
|
|
||||||
io::{self, Write as _},
|
|
||||||
path::Path,
|
|
||||||
sync::Arc,
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
use tracing::{
|
|
||||||
field::{Field, Visit},
|
|
||||||
span, Event, Metadata, Subscriber,
|
|
||||||
};
|
|
||||||
use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer};
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
|
||||||
enum EventType {
|
|
||||||
Begin,
|
|
||||||
Event,
|
|
||||||
End,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A layer to add to a [`tracing_subscriber::Registry`] to output to a chrome
|
|
||||||
/// trace.
|
|
||||||
///
|
|
||||||
/// If you want an easy "set and forget" method of installing this and normal
|
|
||||||
/// tracing logging, call [`initialize_default_subscriber`].
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ChromeTracingLayer {
|
|
||||||
file: Arc<Mutex<std::fs::File>>,
|
|
||||||
start_time: Instant,
|
|
||||||
process_id: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChromeTracingLayer {
|
|
||||||
/// Create a trace which outputs to the given file. The file will be cleared if it exits.
|
|
||||||
pub fn with_file(file: impl AsRef<Path>) -> io::Result<Self> {
|
|
||||||
std::fs::File::create(file).map(|mut file| {
|
|
||||||
writeln!(file, "[").unwrap();
|
|
||||||
ChromeTracingLayer {
|
|
||||||
file: Arc::new(Mutex::new(file)),
|
|
||||||
start_time: Instant::now(),
|
|
||||||
process_id: std::process::id(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_event(
|
|
||||||
&self,
|
|
||||||
mut fields: Option<EventVisitor>,
|
|
||||||
metadata: &'static Metadata<'static>,
|
|
||||||
event_type: EventType,
|
|
||||||
) {
|
|
||||||
if let Some(EventVisitor { trace: false, .. }) = fields {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_time = Instant::now();
|
|
||||||
|
|
||||||
let diff = current_time - self.start_time;
|
|
||||||
let diff_in_us = diff.as_micros();
|
|
||||||
|
|
||||||
let event_type_str = match event_type {
|
|
||||||
EventType::Begin => "B",
|
|
||||||
EventType::Event => "i",
|
|
||||||
EventType::End => "E",
|
|
||||||
};
|
|
||||||
|
|
||||||
let instant_scope = if event_type == EventType::Event {
|
|
||||||
r#","s": "p""#
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = match event_type {
|
|
||||||
EventType::Event => fields
|
|
||||||
.as_mut()
|
|
||||||
.and_then(|fields| fields.message.take())
|
|
||||||
.map_or_else(
|
|
||||||
|| {
|
|
||||||
let name = metadata.name();
|
|
||||||
// The default name for events has a path in it, filter paths only on windows
|
|
||||||
if cfg!(target_os = "windows") {
|
|
||||||
Cow::Owned(name.replace("\\", "\\\\"))
|
|
||||||
} else {
|
|
||||||
Cow::Borrowed(name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Cow::from,
|
|
||||||
),
|
|
||||||
EventType::Begin | EventType::End => Cow::Borrowed(metadata.name()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let category = fields
|
|
||||||
.as_mut()
|
|
||||||
.and_then(|fields| fields.category.take())
|
|
||||||
.map_or_else(|| Cow::Borrowed("trace"), Cow::from);
|
|
||||||
|
|
||||||
let mut file = self.file.lock();
|
|
||||||
writeln!(
|
|
||||||
file,
|
|
||||||
r#"{{ "name": "{}", "cat": "{}", "ph": "{}", "ts": {}, "pid": {}, "tid": {} {} }},"#,
|
|
||||||
name,
|
|
||||||
category,
|
|
||||||
event_type_str,
|
|
||||||
diff_in_us,
|
|
||||||
self.process_id,
|
|
||||||
CURRENT_THREAD_ID.with(|v| *v),
|
|
||||||
instant_scope,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for ChromeTracingLayer {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut file = self.file.lock();
|
|
||||||
writeln!(file, "]").unwrap();
|
|
||||||
file.flush().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
struct EventVisitor {
|
|
||||||
message: Option<String>,
|
|
||||||
category: Option<String>,
|
|
||||||
trace: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visit for EventVisitor {
|
|
||||||
fn record_bool(&mut self, field: &Field, value: bool) {
|
|
||||||
match field.name() {
|
|
||||||
"trace" => self.trace = value,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
|
|
||||||
match field.name() {
|
|
||||||
"message" => self.message = Some(format!("{:?}", value)),
|
|
||||||
"category" => self.category = Some(format!("{:?}", value)),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> Layer<S> for ChromeTracingLayer
|
|
||||||
where
|
|
||||||
S: Subscriber + for<'span> LookupSpan<'span>,
|
|
||||||
{
|
|
||||||
fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
|
|
||||||
let mut event_visitor = EventVisitor::default();
|
|
||||||
event.record(&mut event_visitor);
|
|
||||||
|
|
||||||
self.write_event(Some(event_visitor), event.metadata(), EventType::Event);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
|
|
||||||
let span = ctx.span(id).unwrap();
|
|
||||||
self.write_event(None, span.metadata(), EventType::Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
|
|
||||||
if std::thread::panicking() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let span = ctx.span(id).unwrap();
|
|
||||||
self.write_event(None, span.metadata(), EventType::End);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
use std::{fmt, io, time::Instant};
|
|
||||||
use tracing::{
|
|
||||||
field::{Field, Visit},
|
|
||||||
Event, Level, Subscriber,
|
|
||||||
};
|
|
||||||
use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer};
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
struct FmtEventVisitor {
|
|
||||||
message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visit for FmtEventVisitor {
|
|
||||||
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
|
|
||||||
match field.name() {
|
|
||||||
"message" => self.message = format!("{:?}", value),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum StandardOutput {
|
|
||||||
Out(io::Stdout),
|
|
||||||
Err(io::Stderr),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StandardOutput {
|
|
||||||
fn new(level: &Level) -> Self {
|
|
||||||
match *level {
|
|
||||||
Level::ERROR | Level::WARN => Self::Err(io::stderr()),
|
|
||||||
_ => Self::Out(io::stdout()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_dyn_ref(&mut self) -> &mut dyn io::Write {
|
|
||||||
match self {
|
|
||||||
Self::Out(out) => out,
|
|
||||||
Self::Err(err) => err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FmtLayer {
|
|
||||||
start: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FmtLayer {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
FmtLayer {
|
|
||||||
start: Instant::now(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> Layer<S> for FmtLayer
|
|
||||||
where
|
|
||||||
S: Subscriber + for<'span> LookupSpan<'span>,
|
|
||||||
{
|
|
||||||
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
|
|
||||||
let now = Instant::now();
|
|
||||||
let time = now - self.start;
|
|
||||||
|
|
||||||
let mut visitor = FmtEventVisitor::default();
|
|
||||||
event.record(&mut visitor);
|
|
||||||
|
|
||||||
let mut span_string = String::new();
|
|
||||||
for span in ctx.scope() {
|
|
||||||
if !span_string.is_empty() {
|
|
||||||
span_string.push_str(" | ");
|
|
||||||
}
|
|
||||||
span_string.push_str(span.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
let metadata = event.metadata();
|
|
||||||
let level = match *metadata.level() {
|
|
||||||
Level::ERROR => "ERROR",
|
|
||||||
Level::WARN => "WARN",
|
|
||||||
Level::INFO => "INFO",
|
|
||||||
Level::DEBUG => "DEBUG",
|
|
||||||
Level::TRACE => "TRACE",
|
|
||||||
};
|
|
||||||
|
|
||||||
let module = metadata.module_path().unwrap_or("no module");
|
|
||||||
|
|
||||||
let mut output = StandardOutput::new(metadata.level());
|
|
||||||
let output_ref = output.get_dyn_ref();
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
output_ref,
|
|
||||||
"[{:.6} {}]({})({}): {}",
|
|
||||||
time.as_secs_f64(),
|
|
||||||
level,
|
|
||||||
span_string,
|
|
||||||
module,
|
|
||||||
visitor.message,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
pub use chrome::*;
|
|
||||||
pub use fmt_layer::*;
|
|
||||||
use std::path::Path;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt as _, EnvFilter};
|
|
||||||
|
|
||||||
mod chrome;
|
|
||||||
mod fmt_layer;
|
|
||||||
|
|
||||||
/// Set up the "standard" logger.
|
|
||||||
///
|
|
||||||
/// This is fairly inflexible, but a good default to start with. If you need more customization,
|
|
||||||
/// take what this function does and implement it however you need.
|
|
||||||
///
|
|
||||||
/// If this function is called, you should **not** set up a log-based logger like env_logger
|
|
||||||
/// or fern. This will result in duplicate messages.
|
|
||||||
///
|
|
||||||
/// # Args
|
|
||||||
///
|
|
||||||
/// - `chrome_tracing_path` if set to `Some`, will create a trace compatible with chrome://tracing
|
|
||||||
/// at that location.
|
|
||||||
pub fn initialize_default_subscriber(chrome_trace_path: Option<&Path>) {
|
|
||||||
let chrome_tracing_layer_opt =
|
|
||||||
chrome_trace_path.map(|path| ChromeTracingLayer::with_file(path).unwrap());
|
|
||||||
|
|
||||||
// Tracing currently doesn't support type erasure with layer composition
|
|
||||||
if let Some(chrome_tracing_layer) = chrome_tracing_layer_opt {
|
|
||||||
tracing::subscriber::set_global_default(
|
|
||||||
tracing_subscriber::Registry::default()
|
|
||||||
.with(chrome_tracing_layer)
|
|
||||||
.with(FmtLayer::new())
|
|
||||||
.with(EnvFilter::from_default_env()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
|
||||||
tracing::subscriber::set_global_default(
|
|
||||||
tracing_subscriber::Registry::default()
|
|
||||||
.with(FmtLayer::new())
|
|
||||||
.with(EnvFilter::from_default_env()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing_log::LogTracer::init().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
static CURRENT_THREAD_ID: usize = thread_id::get();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user