1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#[cfg(feature = "counters")]
use std::sync::atomic::{AtomicIsize, Ordering};

/// An internal counter for debugging purposes
///
/// Internally represented as an atomic isize if the `counters` feature is enabled,
/// or compiles to nothing otherwise.
pub struct InternalCounter {
    #[cfg(feature = "counters")]
    value: AtomicIsize,
}

impl InternalCounter {
    /// Creates a counter with value 0.
    #[inline]
    pub const fn new() -> Self {
        InternalCounter {
            #[cfg(feature = "counters")]
            value: AtomicIsize::new(0),
        }
    }

    /// Get the counter's value.
    #[cfg(feature = "counters")]
    #[inline]
    pub fn read(&self) -> isize {
        self.value.load(Ordering::Relaxed)
    }

    /// Get the counter's value.
    ///
    /// Always returns 0 if the `counters` feature is not enabled.
    #[cfg(not(feature = "counters"))]
    #[inline]
    pub fn read(&self) -> isize {
        0
    }

    /// Get and reset the counter's value.
    ///
    /// Always returns 0 if the `counters` feature is not enabled.
    #[cfg(feature = "counters")]
    #[inline]
    pub fn take(&self) -> isize {
        self.value.swap(0, Ordering::Relaxed)
    }

    /// Get and reset the counter's value.
    ///
    /// Always returns 0 if the `counters` feature is not enabled.
    #[cfg(not(feature = "counters"))]
    #[inline]
    pub fn take(&self) -> isize {
        0
    }

    /// Increment the counter by the provided amount.
    #[inline]
    pub fn add(&self, _val: isize) {
        #[cfg(feature = "counters")]
        self.value.fetch_add(_val, Ordering::Relaxed);
    }

    /// Decrement the counter by the provided amount.
    #[inline]
    pub fn sub(&self, _val: isize) {
        #[cfg(feature = "counters")]
        self.value.fetch_add(-_val, Ordering::Relaxed);
    }

    /// Sets the counter to the provided value.
    #[inline]
    pub fn set(&self, _val: isize) {
        #[cfg(feature = "counters")]
        self.value.store(_val, Ordering::Relaxed);
    }
}

impl Clone for InternalCounter {
    fn clone(&self) -> Self {
        InternalCounter {
            #[cfg(feature = "counters")]
            value: AtomicIsize::new(self.read()),
        }
    }
}

impl Default for InternalCounter {
    fn default() -> Self {
        Self::new()
    }
}

impl std::fmt::Debug for InternalCounter {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.read().fmt(f)
    }
}

/// `wgpu-hal`'s internal counters.
#[allow(missing_docs)]
#[derive(Clone, Default)]
pub struct HalCounters {
    // API objects
    pub buffers: InternalCounter,
    pub textures: InternalCounter,
    pub texture_views: InternalCounter,
    pub bind_groups: InternalCounter,
    pub bind_group_layouts: InternalCounter,
    pub render_pipelines: InternalCounter,
    pub compute_pipelines: InternalCounter,
    pub pipeline_layouts: InternalCounter,
    pub samplers: InternalCounter,
    pub command_encoders: InternalCounter,
    pub shader_modules: InternalCounter,
    pub query_sets: InternalCounter,
    pub fences: InternalCounter,

    // Resources
    /// Amount of allocated gpu memory attributed to buffers, in bytes.
    pub buffer_memory: InternalCounter,
    /// Amount of allocated gpu memory attributed to textures, in bytes.
    pub texture_memory: InternalCounter,
    /// Number of gpu memory allocations.
    pub memory_allocations: InternalCounter,
}

/// `wgpu-core`'s internal counters.
#[derive(Clone, Default)]
pub struct CoreCounters {
    // TODO
}

/// All internal counters, exposed for debugging purposes.
#[derive(Clone, Default)]
pub struct InternalCounters {
    /// `wgpu-core` counters.
    pub core: CoreCounters,
    /// `wgpu-hal` counters.
    pub hal: HalCounters,
}