wgpu_core/
error.rs

1use core::fmt;
2use std::error::Error;
3
4use crate::{gfx_select, global::Global, identity::IdentityManagerFactory};
5
6pub struct ErrorFormatter<'a> {
7    writer: &'a mut dyn fmt::Write,
8    global: &'a Global<IdentityManagerFactory>,
9}
10
11impl<'a> ErrorFormatter<'a> {
12    pub fn error(&mut self, err: &dyn Error) {
13        writeln!(self.writer, "    {err}").expect("Error formatting error");
14    }
15
16    pub fn note(&mut self, note: &dyn fmt::Display) {
17        writeln!(self.writer, "      note: {note}").expect("Error formatting error");
18    }
19
20    pub fn label(&mut self, label_key: &str, label_value: &str) {
21        if !label_key.is_empty() && !label_value.is_empty() {
22            self.note(&format!("{label_key} = `{label_value}`"));
23        }
24    }
25
26    pub fn bind_group_label(&mut self, id: &crate::id::BindGroupId) {
27        let global = self.global;
28        let label: String = gfx_select!(id => global.bind_group_label(*id));
29        self.label("bind group", &label);
30    }
31
32    pub fn bind_group_layout_label(&mut self, id: &crate::id::BindGroupLayoutId) {
33        let global = self.global;
34        let label: String = gfx_select!(id => global.bind_group_layout_label(*id));
35        self.label("bind group layout", &label);
36    }
37
38    pub fn render_pipeline_label(&mut self, id: &crate::id::RenderPipelineId) {
39        let global = self.global;
40        let label: String = gfx_select!(id => global.render_pipeline_label(*id));
41        self.label("render pipeline", &label);
42    }
43
44    pub fn compute_pipeline_label(&mut self, id: &crate::id::ComputePipelineId) {
45        let global = self.global;
46        let label: String = gfx_select!(id => global.compute_pipeline_label(*id));
47        self.label("compute pipeline", &label);
48    }
49
50    pub fn buffer_label_with_key(&mut self, id: &crate::id::BufferId, key: &str) {
51        let global = self.global;
52        let label: String = gfx_select!(id => global.buffer_label(*id));
53        self.label(key, &label);
54    }
55
56    pub fn buffer_label(&mut self, id: &crate::id::BufferId) {
57        self.buffer_label_with_key(id, "buffer");
58    }
59
60    pub fn texture_label_with_key(&mut self, id: &crate::id::TextureId, key: &str) {
61        let global = self.global;
62        let label: String = gfx_select!(id => global.texture_label(*id));
63        self.label(key, &label);
64    }
65
66    pub fn texture_label(&mut self, id: &crate::id::TextureId) {
67        self.texture_label_with_key(id, "texture");
68    }
69
70    pub fn texture_view_label_with_key(&mut self, id: &crate::id::TextureViewId, key: &str) {
71        let global = self.global;
72        let label: String = gfx_select!(id => global.texture_view_label(*id));
73        self.label(key, &label);
74    }
75
76    pub fn texture_view_label(&mut self, id: &crate::id::TextureViewId) {
77        self.texture_view_label_with_key(id, "texture view");
78    }
79
80    pub fn sampler_label(&mut self, id: &crate::id::SamplerId) {
81        let global = self.global;
82        let label: String = gfx_select!(id => global.sampler_label(*id));
83        self.label("sampler", &label);
84    }
85
86    pub fn command_buffer_label(&mut self, id: &crate::id::CommandBufferId) {
87        let global = self.global;
88        let label: String = gfx_select!(id => global.command_buffer_label(*id));
89        self.label("command buffer", &label);
90    }
91
92    pub fn query_set_label(&mut self, id: &crate::id::QuerySetId) {
93        let global = self.global;
94        let label: String = gfx_select!(id => global.query_set_label(*id));
95        self.label("query set", &label);
96    }
97}
98
99pub trait PrettyError: Error + Sized {
100    fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
101        fmt.error(self);
102    }
103}
104
105pub fn format_pretty_any(
106    writer: &mut dyn fmt::Write,
107    global: &Global<IdentityManagerFactory>,
108    error: &(dyn Error + 'static),
109) {
110    let mut fmt = ErrorFormatter { writer, global };
111
112    if let Some(pretty_err) = error.downcast_ref::<ContextError>() {
113        return pretty_err.fmt_pretty(&mut fmt);
114    }
115
116    if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderCommandError>() {
117        return pretty_err.fmt_pretty(&mut fmt);
118    }
119    if let Some(pretty_err) = error.downcast_ref::<crate::binding_model::CreateBindGroupError>() {
120        return pretty_err.fmt_pretty(&mut fmt);
121    }
122    if let Some(pretty_err) =
123        error.downcast_ref::<crate::binding_model::CreatePipelineLayoutError>()
124    {
125        return pretty_err.fmt_pretty(&mut fmt);
126    }
127    if let Some(pretty_err) = error.downcast_ref::<crate::command::ExecutionError>() {
128        return pretty_err.fmt_pretty(&mut fmt);
129    }
130    if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderPassErrorInner>() {
131        return pretty_err.fmt_pretty(&mut fmt);
132    }
133    if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderPassError>() {
134        return pretty_err.fmt_pretty(&mut fmt);
135    }
136    if let Some(pretty_err) = error.downcast_ref::<crate::command::ComputePassErrorInner>() {
137        return pretty_err.fmt_pretty(&mut fmt);
138    }
139    if let Some(pretty_err) = error.downcast_ref::<crate::command::ComputePassError>() {
140        return pretty_err.fmt_pretty(&mut fmt);
141    }
142    if let Some(pretty_err) = error.downcast_ref::<crate::command::RenderBundleError>() {
143        return pretty_err.fmt_pretty(&mut fmt);
144    }
145    if let Some(pretty_err) = error.downcast_ref::<crate::command::TransferError>() {
146        return pretty_err.fmt_pretty(&mut fmt);
147    }
148    if let Some(pretty_err) = error.downcast_ref::<crate::command::PassErrorScope>() {
149        return pretty_err.fmt_pretty(&mut fmt);
150    }
151    if let Some(pretty_err) = error.downcast_ref::<crate::track::UsageConflict>() {
152        return pretty_err.fmt_pretty(&mut fmt);
153    }
154    if let Some(pretty_err) = error.downcast_ref::<crate::command::QueryError>() {
155        return pretty_err.fmt_pretty(&mut fmt);
156    }
157
158    // default
159    fmt.error(error)
160}
161
162#[derive(Debug)]
163pub struct ContextError {
164    pub string: &'static str,
165    #[cfg(any(
166        not(target_arch = "wasm32"),
167        all(
168            feature = "fragile-send-sync-non-atomic-wasm",
169            not(target_feature = "atomics")
170        )
171    ))]
172    pub cause: Box<dyn Error + Send + Sync + 'static>,
173    #[cfg(not(any(
174        not(target_arch = "wasm32"),
175        all(
176            feature = "fragile-send-sync-non-atomic-wasm",
177            not(target_feature = "atomics")
178        )
179    )))]
180    pub cause: Box<dyn Error + 'static>,
181    pub label_key: &'static str,
182    pub label: String,
183}
184
185impl PrettyError for ContextError {
186    fn fmt_pretty(&self, fmt: &mut ErrorFormatter) {
187        fmt.error(self);
188        fmt.label(self.label_key, &self.label);
189    }
190}
191
192impl fmt::Display for ContextError {
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        write!(f, "In {}", self.string)
195    }
196}
197
198impl Error for ContextError {
199    fn source(&self) -> Option<&(dyn Error + 'static)> {
200        Some(self.cause.as_ref())
201    }
202}