Files
ab_glyph_rasterizer
addr2line
adler
andrew
approx
arrayvec
ash
atom
backtrace
bitflags
byteorder
calloop
cfg_if
colorful
conrod_core
conrod_derive
conrod_example_shared
conrod_gfx
conrod_glium
conrod_piston
conrod_rendy
conrod_vulkano
conrod_wgpu
conrod_winit
copyless
copypasta
crossbeam
crossbeam_channel
crossbeam_deque
crossbeam_epoch
crossbeam_queue
crossbeam_utils
daggy
dlib
downcast_rs
draw_state
either
fixedbitset
float
fnv
futures
futures_channel
futures_core
futures_executor
futures_io
futures_macro
futures_sink
futures_task
futures_util
async_await
future
io
lock
sink
stream
task
fxhash
getrandom
gfx
gfx_backend_empty
gfx_backend_vulkan
gfx_core
gfx_descriptor
gfx_hal
gfx_memory
gimli
glium
glutin
glutin_egl_sys
glutin_glx_sys
graphics
half
hibitset
inplace_it
input
instant
interpolation
iovec
itoa
lazy_static
lazycell
libc
libloading
line_drawing
linked_hash_map
lock_api
log
maybe_uninit
memchr
memmap
memoffset
miniz_oxide
mio
mio_extras
naga
net2
nix
nom
num
num_bigint
num_complex
num_cpus
num_integer
num_iter
num_rational
num_traits
object
once_cell
ordered_float
ordermap
osmesa_sys
owned_ttf_parser
parking_lot
parking_lot_core
percent_encoding
petgraph
pin_project
pin_project_internal
pin_project_lite
pin_utils
ppv_lite86
proc_macro2
proc_macro_hack
proc_macro_nested
quote
rand
rand_chacha
rand_core
raw_window_handle
read_color
relevant
rendy
rendy_chain
rendy_command
rendy_core
rendy_descriptor
rendy_factory
rendy_frame
rendy_graph
rendy_init
rendy_memory
rendy_mesh
rendy_resource
rendy_shader
rendy_texture
rendy_wsi
rustc_demangle
rustc_hash
rusttype
ryu
same_file
scoped_tls
scopeguard
serde
serde_derive
serde_json
shaderc
shaderc_sys
shared_library
slab
smallvec
smithay_client_toolkit
smithay_clipboard
spirv_headers
stb_truetype
syn
takeable_option
texture
thiserror
thiserror_impl
thread_profiler
time
tracing
tracing_core
ttf_parser
typed_arena
unicode_xid
vecmath
viewport
vk_sys
void
vulkano
buffer
command_buffer
descriptor
device
framebuffer
image
instance
memory
pipeline
query
swapchain
sync
vulkano_shaders
walkdir
wayland_client
wayland_commons
wayland_cursor
wayland_egl
wayland_protocols
wayland_sys
wgpu
wgpu_core
wgpu_types
winit
x11
x11_clipboard
x11_dl
xcb
xcursor
xdg
xml
  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
use crate::Size;
use hal::memory::Properties;

/// Memory utilization stats.
#[derive(Clone, Copy, Debug)]
pub struct MemoryUtilization {
    /// Total number of bytes allocated.
    pub used: Size,
    /// Effective number bytes allocated.
    pub effective: Size,
}

/// Memory utilization of one heap.
#[derive(Clone, Copy, Debug)]
pub struct MemoryHeapUtilization {
    /// Utilization.
    pub utilization: MemoryUtilization,

    /// Memory heap size.
    pub size: Size,
}

/// Memory utilization of one type.
#[derive(Clone, Copy, Debug)]
pub struct MemoryTypeUtilization {
    /// Utilization.
    pub utilization: MemoryUtilization,

    /// Memory type info.
    pub properties: Properties,

    /// Index of heap this memory type uses.
    pub heap_index: usize,
}

/// Total memory utilization.
#[derive(Clone, Debug)]
pub struct TotalMemoryUtilization {
    /// Utilization by types.
    pub types: Vec<MemoryTypeUtilization>,

    /// Utilization by heaps.
    pub heaps: Vec<MemoryHeapUtilization>,
}

impl std::fmt::Display for TotalMemoryUtilization {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        const MB: Size = 1024 * 1024;

        writeln!(fmt, "!!! Memory utilization !!!")?;
        for (index, heap) in self.heaps.iter().enumerate() {
            let size = heap.size;
            let MemoryUtilization { used, effective } = heap.utilization;
            let usage_basis_points = used * 10000 / size;
            let fill = if usage_basis_points > 10000 {
                // Shouldn't happen, but just in case.
                50
            } else {
                (usage_basis_points / 200) as usize
            };
            let effective_basis_points = if used > 0 {
                effective * 10000 / used
            } else {
                10000
            };

            let line = "|".repeat(fill) + &(" ".repeat(50 - fill));
            writeln!(
                fmt,
                "Heap {}:\n{:6} / {:<6} or{} {{ effective:{} }} [{}]",
                format!("{}", index),
                format!("{}MB", used / MB),
                format!("{}MB", size / MB),
                format_basis_points(usage_basis_points),
                format_basis_points(effective_basis_points),
                line
            )?;

            for ty in self.types.iter().filter(|ty| ty.heap_index == index) {
                let properties = ty.properties;
                let MemoryUtilization { used, effective } = ty.utilization;
                let usage_basis_points = used * 10000 / size;
                let effective_basis_points = if used > 0 {
                    effective * 10000 / used
                } else {
                    0
                };

                writeln!(
                    fmt,
                    "         {:>6} or{} {{ effective:{} }} | {:?}",
                    format!("{}MB", used / MB),
                    format_basis_points(usage_basis_points),
                    format_basis_points(effective_basis_points),
                    properties,
                )?;
            }
        }

        Ok(())
    }
}

fn format_basis_points(basis_points: Size) -> String {
    debug_assert!(basis_points <= 10000);
    format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100)
}