rendy_memory/
usage.rs

1//! Defines usage types for memory bocks.
2//! See `Usage` and implementations for details.
3
4use crate::allocator::Kind;
5
6/// Memory usage trait.
7pub trait MemoryUsage: std::fmt::Debug {
8    /// Get set of properties required for the usage.
9    fn properties_required(&self) -> gfx_hal::memory::Properties;
10
11    /// Get comparable fitness value for memory properties.
12    ///
13    /// # Panics
14    ///
15    /// This function will panic if properties set doesn't contain required properties.
16    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32;
17
18    /// Get comparable fitness value for memory allocator.
19    fn allocator_fitness(&self, kind: Kind) -> u32;
20}
21
22impl<T> MemoryUsage for T
23where
24    T: std::ops::Deref + std::fmt::Debug,
25    T::Target: MemoryUsage,
26{
27    fn properties_required(&self) -> gfx_hal::memory::Properties {
28        (&**self).properties_required()
29    }
30    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
31        (&**self).memory_fitness(properties)
32    }
33    fn allocator_fitness(&self, kind: Kind) -> u32 {
34        (&**self).allocator_fitness(kind)
35    }
36}
37
38/// Full speed GPU access.
39/// Optimal for render targets and persistent resources.
40/// Avoid memory with host access.
41#[derive(Clone, Copy, Debug)]
42pub struct Data;
43
44impl MemoryUsage for Data {
45    fn properties_required(&self) -> gfx_hal::memory::Properties {
46        gfx_hal::memory::Properties::DEVICE_LOCAL
47    }
48
49    #[inline]
50    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
51        assert!(properties.contains(gfx_hal::memory::Properties::DEVICE_LOCAL));
52        0 | ((!properties.contains(gfx_hal::memory::Properties::CPU_VISIBLE)) as u32) << 3
53            | ((!properties.contains(gfx_hal::memory::Properties::LAZILY_ALLOCATED)) as u32) << 2
54            | ((!properties.contains(gfx_hal::memory::Properties::CPU_CACHED)) as u32) << 1
55            | ((!properties.contains(gfx_hal::memory::Properties::COHERENT)) as u32) << 0
56    }
57
58    fn allocator_fitness(&self, kind: Kind) -> u32 {
59        match kind {
60            Kind::Dedicated => 1,
61            Kind::Dynamic => 2,
62            Kind::Linear => 0,
63        }
64    }
65}
66
67/// CPU to GPU data flow with update commands.
68/// Used for dynamic buffer data, typically constant buffers.
69/// Host access is guaranteed.
70/// Prefers memory with fast GPU access.
71#[derive(Clone, Copy, Debug)]
72pub struct Dynamic;
73
74impl MemoryUsage for Dynamic {
75    fn properties_required(&self) -> gfx_hal::memory::Properties {
76        gfx_hal::memory::Properties::CPU_VISIBLE
77    }
78
79    #[inline]
80    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
81        assert!(properties.contains(gfx_hal::memory::Properties::CPU_VISIBLE));
82        assert!(!properties.contains(gfx_hal::memory::Properties::LAZILY_ALLOCATED));
83
84        0 | (properties.contains(gfx_hal::memory::Properties::DEVICE_LOCAL) as u32) << 2
85            | (properties.contains(gfx_hal::memory::Properties::COHERENT) as u32) << 1
86            | ((!properties.contains(gfx_hal::memory::Properties::CPU_CACHED)) as u32) << 0
87    }
88
89    fn allocator_fitness(&self, kind: Kind) -> u32 {
90        match kind {
91            Kind::Dedicated => 1,
92            Kind::Dynamic => 2,
93            Kind::Linear => 0,
94        }
95    }
96}
97
98/// CPU to GPU data flow with mapping.
99/// Used for staging data before copying to the `Data` memory.
100/// Host access is guaranteed.
101#[derive(Clone, Copy, Debug)]
102pub struct Upload;
103
104impl MemoryUsage for Upload {
105    fn properties_required(&self) -> gfx_hal::memory::Properties {
106        gfx_hal::memory::Properties::CPU_VISIBLE
107    }
108
109    #[inline]
110    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
111        assert!(properties.contains(gfx_hal::memory::Properties::CPU_VISIBLE));
112        assert!(!properties.contains(gfx_hal::memory::Properties::LAZILY_ALLOCATED));
113
114        0 | ((!properties.contains(gfx_hal::memory::Properties::DEVICE_LOCAL)) as u32) << 2
115            | (properties.contains(gfx_hal::memory::Properties::COHERENT) as u32) << 1
116            | ((!properties.contains(gfx_hal::memory::Properties::CPU_CACHED)) as u32) << 0
117    }
118
119    fn allocator_fitness(&self, kind: Kind) -> u32 {
120        match kind {
121            Kind::Dedicated => 0,
122            Kind::Dynamic => 1,
123            Kind::Linear => 2,
124        }
125    }
126}
127
128/// GPU to CPU data flow with mapping.
129/// Used for copying data from `Data` memory to be read by the host.
130/// Host access is guaranteed.
131#[derive(Clone, Copy, Debug)]
132pub struct Download;
133
134impl MemoryUsage for Download {
135    fn properties_required(&self) -> gfx_hal::memory::Properties {
136        gfx_hal::memory::Properties::CPU_VISIBLE
137    }
138
139    #[inline]
140    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
141        assert!(properties.contains(gfx_hal::memory::Properties::CPU_VISIBLE));
142        assert!(!properties.contains(gfx_hal::memory::Properties::LAZILY_ALLOCATED));
143
144        0 | ((!properties.contains(gfx_hal::memory::Properties::DEVICE_LOCAL)) as u32) << 2
145            | (properties.contains(gfx_hal::memory::Properties::CPU_CACHED) as u32) << 1
146            | (properties.contains(gfx_hal::memory::Properties::COHERENT) as u32) << 0
147    }
148
149    fn allocator_fitness(&self, kind: Kind) -> u32 {
150        match kind {
151            Kind::Dedicated => 0,
152            Kind::Dynamic => 1,
153            Kind::Linear => 2,
154        }
155    }
156}
157
158/// Well-known memory usage types.
159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
160pub enum MemoryUsageValue {
161    /// See [`Data`]
162    ///
163    /// [`Data`]: struct.Data.html
164    Data,
165
166    /// See [`Dynamic`]
167    ///
168    /// [`Dynamic`]: struct.Dynamic.html
169    Dynamic,
170
171    /// See [`Upload`]
172    ///
173    /// [`Upload`]: struct.Upload.html
174    Upload,
175
176    /// See [`Download`]
177    ///
178    /// [`Download`]: struct.Download.html
179    Download,
180}
181
182/// Memory usage trait.
183impl MemoryUsage for MemoryUsageValue {
184    fn properties_required(&self) -> gfx_hal::memory::Properties {
185        match self {
186            MemoryUsageValue::Data => Data.properties_required(),
187            MemoryUsageValue::Dynamic => Dynamic.properties_required(),
188            MemoryUsageValue::Upload => Upload.properties_required(),
189            MemoryUsageValue::Download => Download.properties_required(),
190        }
191    }
192
193    fn memory_fitness(&self, properties: gfx_hal::memory::Properties) -> u32 {
194        match self {
195            MemoryUsageValue::Data => Data.memory_fitness(properties),
196            MemoryUsageValue::Dynamic => Dynamic.memory_fitness(properties),
197            MemoryUsageValue::Upload => Upload.memory_fitness(properties),
198            MemoryUsageValue::Download => Download.memory_fitness(properties),
199        }
200    }
201
202    fn allocator_fitness(&self, kind: Kind) -> u32 {
203        match self {
204            MemoryUsageValue::Data => Data.allocator_fitness(kind),
205            MemoryUsageValue::Dynamic => Dynamic.allocator_fitness(kind),
206            MemoryUsageValue::Upload => Upload.allocator_fitness(kind),
207            MemoryUsageValue::Download => Download.allocator_fitness(kind),
208        }
209    }
210}