1 //! Physical graphics devices.
2 //!
3 //! The [`PhysicalDevice`][PhysicalDevice] trait specifies the API a backend
4 //! must provide for dealing with and querying a physical device, such as
5 //! a particular GPU.
6 //!
7 //! An [adapter][Adapter] is a struct containing a physical device and metadata
8 //! for a particular GPU, generally created from an [instance][crate::Instance]
9 //! of that [backend][crate::Backend].
10 
11 use crate::{
12     device, format, image, memory,
13     queue::{QueueGroup, QueuePriority},
14     Backend, Features, PhysicalDeviceProperties,
15 };
16 
17 use std::{any::Any, fmt};
18 
19 /// A description for a single type of memory in a heap.
20 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
21 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22 pub struct MemoryType {
23     /// Properties of the associated memory, such as synchronization
24     /// properties or whether it's on the CPU or GPU.
25     pub properties: memory::Properties,
26     /// Index to the underlying memory heap in `Gpu::memory_heaps`
27     pub heap_index: usize,
28 }
29 
30 /// A description for a memory heap.
31 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
32 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33 pub struct MemoryHeap {
34     /// Total size of the heap.
35     pub size: u64,
36     /// Heap flags.
37     pub flags: memory::HeapFlags,
38 }
39 
40 /// Types of memory supported by this adapter and available memory.
41 #[derive(Clone, Debug, Eq, PartialEq)]
42 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43 pub struct MemoryProperties {
44     /// Each memory type is associated with one heap of `memory_heaps`.
45     /// Multiple types can point to the same heap.
46     pub memory_types: Vec<MemoryType>,
47     /// Memory heaps with their size in bytes.
48     pub memory_heaps: Vec<MemoryHeap>,
49 }
50 
51 /// Represents a combination of a [logical device][crate::device::Device] and the
52 /// [hardware queues][QueueGroup] it provides.
53 ///
54 /// This structure is typically created from an [adapter][crate::adapter::Adapter].
55 #[derive(Debug)]
56 pub struct Gpu<B: Backend> {
57     /// [Logical device][crate::device::Device] for a given backend.
58     pub device: B::Device,
59     /// The [command queues][crate::queue::Queue] that the device provides.
60     pub queue_groups: Vec<QueueGroup<B>>,
61 }
62 
63 /// Represents a physical device (such as a GPU) capable of supporting the given backend.
64 pub trait PhysicalDevice<B: Backend>: fmt::Debug + Any + Send + Sync {
65     /// Create a new [logical device][crate::device::Device] with the requested features.
66     /// If `requested_features` is [empty][crate::Features::empty], then only
67     /// the core features are supported.
68     ///
69     /// # Arguments
70     ///
71     /// * `families` - which [queue families][crate::queue::family::QueueFamily]
72     ///   to create queues from. The implementation may allocate more processing time to
73     ///   the queues with higher [priority][QueuePriority].
74     /// * `requested_features` - device features to enable. Must be a subset of
75     ///   the [features][PhysicalDevice::features] supported by this device.
76     ///
77     /// # Errors
78     ///
79     /// - Returns `TooManyObjects` if the implementation can't create a new logical device.
80     /// - Returns `MissingFeature` if the implementation does not support a requested feature.
81     ///
82     /// # Examples
83     ///
84     /// ```no_run
85     /// # extern crate gfx_backend_empty as empty;
86     /// # extern crate gfx_hal;
87     /// # fn main() {
88     /// use gfx_hal::{adapter::PhysicalDevice, Features};
89     ///
90     /// # let physical_device: empty::PhysicalDevice = return;
91     /// # let family: empty::QueueFamily = return;
92     /// # unsafe {
93     /// let gpu = physical_device.open(&[(&family, &[1.0; 1])], Features::empty());
94     /// # }}
95     /// ```
open( &self, families: &[(&B::QueueFamily, &[QueuePriority])], requested_features: Features, ) -> Result<Gpu<B>, device::CreationError>96     unsafe fn open(
97         &self,
98         families: &[(&B::QueueFamily, &[QueuePriority])],
99         requested_features: Features,
100     ) -> Result<Gpu<B>, device::CreationError>;
101 
102     /// Fetch details for a particular format.
format_properties(&self, format: Option<format::Format>) -> format::Properties103     fn format_properties(&self, format: Option<format::Format>) -> format::Properties;
104 
105     /// Fetch details for a particular image format.
image_format_properties( &self, format: format::Format, dimensions: u8, tiling: image::Tiling, usage: image::Usage, view_caps: image::ViewCapabilities, ) -> Option<image::FormatProperties>106     fn image_format_properties(
107         &self,
108         format: format::Format,
109         dimensions: u8,
110         tiling: image::Tiling,
111         usage: image::Usage,
112         view_caps: image::ViewCapabilities,
113     ) -> Option<image::FormatProperties>;
114 
115     /// Fetch details for the memory regions provided by the device.
memory_properties(&self) -> MemoryProperties116     fn memory_properties(&self) -> MemoryProperties;
117 
118     /// Returns the features of this `PhysicalDevice`. This usually depends on the graphics API being
119     /// used, as well as the actual platform underneath.
features(&self) -> Features120     fn features(&self) -> Features;
121 
122     /// Returns the properties of this `PhysicalDevice`. Similarly to `Features`, they
123     // depend on the platform, but unlike features, these are immutable and can't be switched on.
properties(&self) -> PhysicalDeviceProperties124     fn properties(&self) -> PhysicalDeviceProperties;
125 
126     /// Check cache compatibility with the `PhysicalDevice`.
is_valid_cache(&self, _cache: &[u8]) -> bool127     fn is_valid_cache(&self, _cache: &[u8]) -> bool {
128         false
129     }
130 }
131 
132 /// The type of a physical graphics device
133 #[derive(Clone, PartialEq, Eq, Debug)]
134 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
135 pub enum DeviceType {
136     /// Other
137     Other = 0,
138     /// Integrated
139     IntegratedGpu = 1,
140     /// Discrete
141     DiscreteGpu = 2,
142     /// Virtual / Hosted
143     VirtualGpu = 3,
144     /// CPU / Software Rendering
145     Cpu = 4,
146 }
147 
148 /// Metadata about a backend [adapter][Adapter].
149 #[derive(Clone, Debug, Eq, PartialEq)]
150 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
151 pub struct AdapterInfo {
152     /// Adapter name
153     pub name: String,
154     /// PCI ID of the device vendor
155     pub vendor: usize,
156     /// PCI ID of the device
157     pub device: usize,
158     /// Type of device
159     pub device_type: DeviceType,
160 }
161 
162 /// Information about a graphics device, supported by the backend.
163 ///
164 /// The list of available adapters is obtained by calling
165 /// [`Instance::enumerate_adapters`][crate::Instance::enumerate_adapters].
166 ///
167 /// To create a [`Gpu`][Gpu] from this type you can use the [`open`](PhysicalDevice::open)
168 /// method on its [`physical_device`][Adapter::physical_device] field.
169 #[derive(Debug)]
170 pub struct Adapter<B: Backend> {
171     /// General information about this adapter.
172     pub info: AdapterInfo,
173     /// Actual [physical device][PhysicalDevice].
174     pub physical_device: B::PhysicalDevice,
175     /// [Queue families][crate::queue::family::QueueFamily] supported by this adapter.
176     pub queue_families: Vec<B::QueueFamily>,
177 }
178