grr/
debug.rs

1use crate::__gl;
2use crate::__gl::types::{GLenum, GLuint};
3use crate::device::Device;
4
5/// Message filter.
6#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub enum MsgFilter<T> {
8    /// Referencing all values of the type `T`.
9    All,
10    ///
11    Some(T),
12}
13
14impl MsgFilter<DebugSource> {
15    fn as_gl(self) -> GLenum {
16        match self {
17            MsgFilter::All => __gl::DONT_CARE,
18            MsgFilter::Some(v) => v as _,
19        }
20    }
21}
22
23impl MsgFilter<DebugType> {
24    fn as_gl(self) -> GLenum {
25        match self {
26            MsgFilter::All => __gl::DONT_CARE,
27            MsgFilter::Some(v) => v as _,
28        }
29    }
30}
31
32bitflags!(
33    /// Debug report flags.
34    ///
35    /// Denotes which events will trigger a debug report.
36    pub struct DebugReport: GLenum {
37        const NOTIFICATION = __gl::DEBUG_SEVERITY_NOTIFICATION;
38        const WARNING = __gl::DEBUG_SEVERITY_MEDIUM;
39        const ERROR = __gl::DEBUG_SEVERITY_HIGH;
40        const PERFORMANCE_WARNING = __gl::DEBUG_SEVERITY_LOW;
41        const FULL = Self::NOTIFICATION.bits | Self::WARNING.bits | Self::ERROR.bits | Self::PERFORMANCE_WARNING.bits;
42    }
43);
44
45/// Debug message source.
46#[repr(u32)]
47#[derive(Debug, Copy, Clone, PartialEq, Eq)]
48pub enum DebugSource {
49    Api = __gl::DEBUG_SOURCE_API,
50    ShaderCompiler = __gl::DEBUG_SOURCE_SHADER_COMPILER,
51    Wsi = __gl::DEBUG_SOURCE_WINDOW_SYSTEM,
52    ThirdParty = __gl::DEBUG_SOURCE_THIRD_PARTY,
53    Application = __gl::DEBUG_SOURCE_APPLICATION,
54    Other = __gl::DEBUG_SOURCE_OTHER,
55}
56
57/// Debug message type.
58#[repr(u32)]
59#[derive(Debug, Copy, Clone, PartialEq, Eq)]
60pub enum DebugType {
61    Error = __gl::DEBUG_TYPE_ERROR,
62    Deprecated = __gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR,
63    UndefinedBehavior = __gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR,
64    Performance = __gl::DEBUG_TYPE_PERFORMANCE,
65    Portability = __gl::DEBUG_TYPE_PORTABILITY,
66    Marker = __gl::DEBUG_TYPE_MARKER,
67    PushGroup = __gl::DEBUG_TYPE_PUSH_GROUP,
68    PopGroup = __gl::DEBUG_TYPE_POP_GROUP,
69    Other = __gl::DEBUG_TYPE_OTHER,
70}
71
72///
73pub type DebugCallback = fn(DebugReport, DebugSource, DebugType, u32, &str);
74
75///
76#[repr(u32)]
77#[derive(Debug, Copy, Clone, PartialEq, Eq)]
78pub enum ObjectType {
79    Buffer = __gl::BUFFER,
80    Shader = __gl::SHADER,
81    Image = __gl::TEXTURE,
82    VertexArray = __gl::VERTEX_ARRAY,
83    Pipeline = __gl::PROGRAM,
84    Framebuffer = __gl::FRAMEBUFFER,
85    Renderbuffer = __gl::RENDERBUFFER,
86    Sampler = __gl::SAMPLER,
87}
88
89pub trait Object: Copy {
90    const TYPE: ObjectType;
91
92    fn handle(&self) -> GLuint;
93}
94
95pub(crate) unsafe fn set_debug_message_control(
96    ctxt: &__gl::Gl,
97    enable: bool,
98    src: MsgFilter<DebugSource>,
99    ty: MsgFilter<DebugType>,
100    flags: DebugReport,
101    ids: Option<&[u32]>,
102) {
103    let src = src.as_gl();
104    let ty = ty.as_gl();
105    let num_ids = match ids {
106        Some(ids) => ids.len() as i32,
107        None => 0,
108    };
109    let id_ptr = match ids {
110        Some(ids) => ids.as_ptr(),
111        None => std::ptr::null(),
112    };
113    let enable = if enable { __gl::TRUE } else { __gl::FALSE };
114
115    if flags.contains(DebugReport::NOTIFICATION) {
116        ctxt.DebugMessageControl(
117            src,
118            ty,
119            DebugReport::NOTIFICATION.bits(),
120            num_ids,
121            id_ptr,
122            enable,
123        );
124    }
125    if flags.contains(DebugReport::WARNING) {
126        ctxt.DebugMessageControl(
127            src,
128            ty,
129            DebugReport::WARNING.bits(),
130            num_ids,
131            id_ptr,
132            enable,
133        );
134    }
135    if flags.contains(DebugReport::ERROR) {
136        ctxt.DebugMessageControl(src, ty, DebugReport::ERROR.bits(), num_ids, id_ptr, enable);
137    }
138    if flags.contains(DebugReport::PERFORMANCE_WARNING) {
139        ctxt.DebugMessageControl(
140            src,
141            ty,
142            DebugReport::PERFORMANCE_WARNING.bits(),
143            num_ids,
144            id_ptr,
145            enable,
146        );
147    }
148}
149
150impl Device {
151    /// Associate a name with an object.
152    pub unsafe fn object_name<T: Object>(&self, object: T, name: &str) {
153        let label = name.as_bytes();
154        self.0.ObjectLabel(
155            T::TYPE as _,
156            object.handle(),
157            label.len() as _,
158            label.as_ptr() as *const _,
159        );
160    }
161
162    pub unsafe fn enable_debug_message(
163        &self,
164        src: MsgFilter<DebugSource>,
165        ty: MsgFilter<DebugType>,
166        flags: DebugReport,
167        ids: Option<&[u32]>,
168    ) {
169        set_debug_message_control(&self.0, true, src, ty, flags, ids);
170    }
171
172    pub unsafe fn disable_debug_message(
173        &self,
174        src: MsgFilter<DebugSource>,
175        ty: MsgFilter<DebugType>,
176        flags: DebugReport,
177        ids: Option<&[u32]>,
178    ) {
179        set_debug_message_control(&self.0, false, src, ty, flags, ids);
180    }
181
182    pub unsafe fn begin_debug_marker(&self, src: DebugSource, id: u32, msg: &str) {
183        self.0
184            .PushDebugGroup(src as _, id, msg.len() as _, msg.as_ptr() as *const _);
185    }
186
187    pub unsafe fn end_debug_marker(&self) {
188        self.0.PopDebugGroup();
189    }
190}