wgpu_core/
error.rs

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