1 #![deny(missing_debug_implementations, missing_docs, unused)]
2 
3 //! Low-level graphics abstraction for Rust. Mostly operates on data, not types.
4 //! Designed for use by libraries and higher-level abstractions only.
5 
6 #[macro_use]
7 extern crate bitflags;
8 
9 #[cfg(feature = "serde")]
10 #[macro_use]
11 extern crate serde;
12 
13 use std::any::Any;
14 use std::fmt;
15 use std::hash::Hash;
16 
17 pub mod adapter;
18 pub mod buffer;
19 pub mod command;
20 pub mod device;
21 pub mod format;
22 pub mod image;
23 pub mod memory;
24 pub mod pass;
25 pub mod pool;
26 pub mod pso;
27 pub mod query;
28 pub mod queue;
29 pub mod window;
30 
31 /// Prelude module re-exports all the traits necessary to use gfx-hal.
32 pub mod prelude {
33     pub use crate::{
34         adapter::PhysicalDevice as _,
35         command::CommandBuffer as _,
36         device::Device as _,
37         pool::CommandPool as _,
38         pso::DescriptorPool as _,
39         queue::{CommandQueue as _, QueueFamily as _},
40         window::{PresentationSurface as _, Surface as _, Swapchain as _},
41         Instance as _,
42     };
43 }
44 
45 /// Draw vertex count.
46 pub type VertexCount = u32;
47 /// Draw vertex base offset.
48 pub type VertexOffset = i32;
49 /// Draw number of indices.
50 pub type IndexCount = u32;
51 /// Draw number of instances.
52 pub type InstanceCount = u32;
53 /// Indirect draw calls count.
54 pub type DrawCount = u32;
55 /// Number of work groups.
56 pub type WorkGroupCount = [u32; 3];
57 
58 bitflags! {
59     //TODO: add a feature for non-normalized samplers
60     //TODO: add a feature for mutable comparison samplers
61     /// Features that the device supports.
62     /// These only include features of the core interface and not API extensions.
63     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
64     pub struct Features: u128 {
65         /// Bit mask of Vulkan Core features.
66         const CORE_MASK = 0xFFFF_FFFF_FFFF_FFFF;
67         /// Bit mask of Vulkan Portability features.
68         const PORTABILITY_MASK  = 0x0000_FFFF_0000_0000_0000_0000;
69         /// Bit mask for extra WebGPU features.
70         const WEBGPU_MASK = 0xFFFF_0000_0000_0000_0000_0000;
71 
72         /// Support for robust buffer access.
73         /// Buffer access by SPIR-V shaders is checked against the buffer/image boundaries.
74         const ROBUST_BUFFER_ACCESS = 0x0000_0000_0000_0001;
75         /// Support the full 32-bit range of indexed for draw calls.
76         /// If not supported, the maximum index value is determined by `Limits::max_draw_index_value`.
77         const FULL_DRAW_INDEX_U32 = 0x0000_0000_0000_0002;
78         /// Support cube array image views.
79         const IMAGE_CUBE_ARRAY = 0x0000_0000_0000_0004;
80         /// Support different color blending settings per attachments on graphics pipeline creation.
81         const INDEPENDENT_BLENDING = 0x0000_0000_0000_0008;
82         /// Support geometry shader.
83         const GEOMETRY_SHADER = 0x0000_0000_0000_0010;
84         /// Support tessellation shaders.
85         const TESSELLATION_SHADER = 0x0000_0000_0000_0020;
86         /// Support per-sample shading and multisample interpolation.
87         const SAMPLE_RATE_SHADING = 0x0000_0000_0000_0040;
88         /// Support dual source blending.
89         const DUAL_SRC_BLENDING = 0x0000_0000_0000_0080;
90         /// Support logic operations.
91         const LOGIC_OP = 0x0000_0000_0000_0100;
92         /// Support multiple draws per indirect call.
93         const MULTI_DRAW_INDIRECT = 0x0000_0000_0000_0200;
94         /// Support indirect drawing with first instance value.
95         /// If not supported the first instance value **must** be 0.
96         const DRAW_INDIRECT_FIRST_INSTANCE = 0x0000_0000_0000_0400;
97         /// Support depth clamping.
98         const DEPTH_CLAMP = 0x0000_0000_0000_0800;
99         /// Support depth bias clamping.
100         const DEPTH_BIAS_CLAMP = 0x0000_0000_0000_1000;
101         /// Support non-fill polygon modes.
102         const NON_FILL_POLYGON_MODE = 0x0000_0000_0000_2000;
103         /// Support depth bounds test.
104         const DEPTH_BOUNDS = 0x0000_0000_0000_4000;
105         /// Support lines with width other than 1.0.
106         const LINE_WIDTH = 0x0000_0000_0000_8000;
107         /// Support points with size greater than 1.0.
108         const POINT_SIZE = 0x0000_0000_0001_0000;
109         /// Support replacing alpha values with 1.0.
110         const ALPHA_TO_ONE = 0x0000_0000_0002_0000;
111         /// Support multiple viewports and scissors.
112         const MULTI_VIEWPORTS = 0x0000_0000_0004_0000;
113         /// Support anisotropic filtering.
114         const SAMPLER_ANISOTROPY = 0x0000_0000_0008_0000;
115         /// Support ETC2 texture compression formats.
116         const FORMAT_ETC2 = 0x0000_0000_0010_0000;
117         /// Support ASTC (LDR) texture compression formats.
118         const FORMAT_ASTC_LDR = 0x0000_0000_0020_0000;
119         /// Support BC texture compression formats.
120         const FORMAT_BC = 0x0000_0000_0040_0000;
121         /// Support precise occlusion queries, returning the actual number of samples.
122         /// If not supported, queries return a non-zero value when at least **one** sample passes.
123         const PRECISE_OCCLUSION_QUERY = 0x0000_0000_0080_0000;
124         /// Support query of pipeline statistics.
125         const PIPELINE_STATISTICS_QUERY = 0x0000_0000_0100_0000;
126         /// Support unordered access stores and atomic ops in the vertex, geometry
127         /// and tessellation shader stage.
128         /// If not supported, the shader resources **must** be annotated as read-only.
129         const VERTEX_STORES_AND_ATOMICS = 0x0000_0000_0200_0000;
130         /// Support unordered access stores and atomic ops in the fragment shader stage
131         /// If not supported, the shader resources **must** be annotated as read-only.
132         const FRAGMENT_STORES_AND_ATOMICS = 0x0000_0000_0400_0000;
133         ///
134         const SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE = 0x0000_0000_0800_0000;
135         ///
136         const SHADER_IMAGE_GATHER_EXTENDED = 0x0000_0000_1000_0000;
137         ///
138         const SHADER_STORAGE_IMAGE_EXTENDED_FORMATS = 0x0000_0000_2000_0000;
139         ///
140         const SHADER_STORAGE_IMAGE_MULTISAMPLE = 0x0000_0000_4000_0000;
141         ///
142         const SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT = 0x0000_0000_8000_0000;
143         ///
144         const SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT = 0x0000_0001_0000_0000;
145         ///
146         const SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING = 0x0000_0002_0000_0000;
147         ///
148         const SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING = 0x0000_0004_0000_0000;
149         ///
150         const SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING = 0x0000_0008_0000_0000;
151         ///
152         const SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING = 0x0000_0010_0000_0000;
153         ///
154         const SHADER_CLIP_DISTANCE = 0x0000_0020_0000_0000;
155         ///
156         const SHADER_CULL_DISTANCE = 0x0000_0040_0000_0000;
157         ///
158         const SHADER_FLOAT64 = 0x0000_0080_0000_0000;
159         ///
160         const SHADER_INT64 = 0x0000_0100_0000_0000;
161         ///
162         const SHADER_INT16 = 0x0000_0200_0000_0000;
163         ///
164         const SHADER_RESOURCE_RESIDENCY = 0x0000_0400_0000_0000;
165         ///
166         const SHADER_RESOURCE_MIN_LOD = 0x0000_0800_0000_0000;
167         ///
168         const SPARSE_BINDING = 0x0000_1000_0000_0000;
169         ///
170         const SPARSE_RESIDENCY_BUFFER = 0x0000_2000_0000_0000;
171         ///
172         const SPARSE_RESIDENCY_IMAGE_2D = 0x0000_4000_0000_0000;
173         ///
174         const SPARSE_RESIDENCY_IMAGE_3D = 0x0000_8000_0000_0000;
175         ///
176         const SPARSE_RESIDENCY_2_SAMPLES = 0x0001_0000_0000_0000;
177         ///
178         const SPARSE_RESIDENCY_4_SAMPLES = 0x0002_0000_0000_0000;
179         ///
180         const SPARSE_RESIDENCY_8_SAMPLES = 0x0004_0000_0000_0000;
181         ///
182         const SPARSE_RESIDENCY_16_SAMPLES = 0x0008_0000_0000_0000;
183         ///
184         const SPARSE_RESIDENCY_ALIASED = 0x0010_0000_0000_0000;
185         ///
186         const VARIABLE_MULTISAMPLE_RATE = 0x0020_0000_0000_0000;
187         ///
188         const INHERITED_QUERIES = 0x0040_0000_0000_0000;
189         /// Support for
190         const SAMPLER_MIRROR_CLAMP_EDGE = 0x0100_0000_0000_0000;
191 
192         /// Support triangle fan primitive topology.
193         const TRIANGLE_FAN = 0x0001 << 64;
194         /// Support separate stencil reference values for front and back sides.
195         const SEPARATE_STENCIL_REF_VALUES = 0x0002 << 64;
196         /// Support manually specified vertex attribute rates (divisors).
197         const INSTANCE_RATE = 0x0004 << 64;
198         /// Support non-zero mipmap bias on samplers.
199         const SAMPLER_MIP_LOD_BIAS = 0x0008 << 64;
200 
201         /// Make the NDC coordinate system pointing Y up, to match D3D and Metal.
202         const NDC_Y_UP = 0x01 << 80;
203     }
204 }
205 
206 bitflags! {
207     /// Features that the device supports natively, but is able to emulate.
208     #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
209     pub struct Hints: u32 {
210         /// Support indexed, instanced drawing with base vertex and instance.
211         const BASE_VERTEX_INSTANCE_DRAWING = 0x0001;
212     }
213 }
214 
215 /// Resource limits of a particular graphics device.
216 #[derive(Clone, Copy, Debug, Default, PartialEq)]
217 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
218 pub struct Limits {
219     /// Maximum supported image 1D size.
220     pub max_image_1d_size: image::Size,
221     /// Maximum supported image 2D size.
222     pub max_image_2d_size: image::Size,
223     /// Maximum supported image 3D size.
224     pub max_image_3d_size: image::Size,
225     /// Maximum supported image cube size.
226     pub max_image_cube_size: image::Size,
227     /// Maximum supporter image array size.
228     pub max_image_array_layers: image::Layer,
229     /// Maximum number of elements for the BufferView to see.
230     pub max_texel_elements: usize,
231     ///
232     pub max_uniform_buffer_range: buffer::Offset,
233     ///
234     pub max_storage_buffer_range: buffer::Offset,
235     ///
236     pub max_push_constants_size: usize,
237     ///
238     pub max_memory_allocation_count: usize,
239     ///
240     pub max_sampler_allocation_count: usize,
241     ///
242     pub max_bound_descriptor_sets: pso::DescriptorSetIndex,
243     ///
244     pub max_framebuffer_layers: usize,
245     ///
246     pub max_per_stage_descriptor_samplers: usize,
247     ///
248     pub max_per_stage_descriptor_uniform_buffers: usize,
249     ///
250     pub max_per_stage_descriptor_storage_buffers: usize,
251     ///
252     pub max_per_stage_descriptor_sampled_images: usize,
253     ///
254     pub max_per_stage_descriptor_storage_images: usize,
255     ///
256     pub max_per_stage_descriptor_input_attachments: usize,
257     ///
258     pub max_per_stage_resources: usize,
259 
260     ///
261     pub max_descriptor_set_samplers: usize,
262     ///
263     pub max_descriptor_set_uniform_buffers: usize,
264     ///
265     pub max_descriptor_set_uniform_buffers_dynamic: usize,
266     ///
267     pub max_descriptor_set_storage_buffers: usize,
268     ///
269     pub max_descriptor_set_storage_buffers_dynamic: usize,
270     ///
271     pub max_descriptor_set_sampled_images: usize,
272     ///
273     pub max_descriptor_set_storage_images: usize,
274     ///
275     pub max_descriptor_set_input_attachments: usize,
276 
277     /// Maximum number of vertex input attributes that can be specified for a graphics pipeline.
278     pub max_vertex_input_attributes: usize,
279     /// Maximum number of vertex buffers that can be specified for providing vertex attributes to a graphics pipeline.
280     pub max_vertex_input_bindings: usize,
281     /// Maximum vertex input attribute offset that can be added to the vertex input binding stride.
282     pub max_vertex_input_attribute_offset: usize,
283     /// Maximum vertex input binding stride that can be specified in a vertex input binding.
284     pub max_vertex_input_binding_stride: usize,
285     /// Maximum number of components of output variables which can be output by a vertex shader.
286     pub max_vertex_output_components: usize,
287 
288     /// Maximum number of vertices for each patch.
289     pub max_patch_size: pso::PatchSize,
290     ///
291     pub max_geometry_shader_invocations: usize,
292     ///
293     pub max_geometry_input_components: usize,
294     ///
295     pub max_geometry_output_components: usize,
296     ///
297     pub max_geometry_output_vertices: usize,
298     ///
299     pub max_geometry_total_output_components: usize,
300     ///
301     pub max_fragment_input_components: usize,
302     ///
303     pub max_fragment_output_attachments: usize,
304     ///
305     pub max_fragment_dual_source_attachments: usize,
306     ///
307     pub max_fragment_combined_output_resources: usize,
308 
309     ///
310     pub max_compute_shared_memory_size: usize,
311     ///
312     pub max_compute_work_group_count: WorkGroupCount,
313     ///
314     pub max_compute_work_group_invocations: usize,
315     ///
316     pub max_compute_work_group_size: [u32; 3],
317 
318     ///
319     pub max_draw_indexed_index_value: IndexCount,
320     ///
321     pub max_draw_indirect_count: InstanceCount,
322 
323     ///
324     pub max_sampler_lod_bias: f32,
325     /// Maximum degree of sampler anisotropy.
326     pub max_sampler_anisotropy: f32,
327 
328     /// Maximum number of viewports.
329     pub max_viewports: usize,
330     ///
331     pub max_viewport_dimensions: [image::Size; 2],
332     ///
333     pub max_framebuffer_extent: image::Extent,
334 
335     ///
336     pub min_memory_map_alignment: usize,
337     ///
338     pub buffer_image_granularity: buffer::Offset,
339     /// The alignment of the start of buffer used as a texel buffer, in bytes, non-zero.
340     pub min_texel_buffer_offset_alignment: buffer::Offset,
341     /// The alignment of the start of buffer used for uniform buffer updates, in bytes, non-zero.
342     pub min_uniform_buffer_offset_alignment: buffer::Offset,
343     /// The alignment of the start of buffer used as a storage buffer, in bytes, non-zero.
344     pub min_storage_buffer_offset_alignment: buffer::Offset,
345     /// Number of samples supported for color attachments of framebuffers (floating/fixed point).
346     pub framebuffer_color_sample_counts: image::NumSamples,
347     /// Number of samples supported for depth attachments of framebuffers.
348     pub framebuffer_depth_sample_counts: image::NumSamples,
349     /// Number of samples supported for stencil attachments of framebuffers.
350     pub framebuffer_stencil_sample_counts: image::NumSamples,
351     /// Maximum number of color attachments that can be used by a subpass in a render pass.
352     pub max_color_attachments: usize,
353     ///
354     pub standard_sample_locations: bool,
355     /// The alignment of the start of the buffer used as a GPU copy source, in bytes, non-zero.
356     pub optimal_buffer_copy_offset_alignment: buffer::Offset,
357     /// The alignment of the row pitch of the texture data stored in a buffer that is
358     /// used in a GPU copy operation, in bytes, non-zero.
359     pub optimal_buffer_copy_pitch_alignment: buffer::Offset,
360     /// Size and alignment in bytes that bounds concurrent access to host-mapped device memory.
361     pub non_coherent_atom_size: usize,
362 
363     /// The alignment of the vertex buffer stride.
364     pub min_vertex_input_binding_stride_alignment: buffer::Offset,
365 }
366 
367 /// An enum describing the type of an index value in a slice's index buffer
368 #[allow(missing_docs)]
369 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
370 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
371 #[repr(u8)]
372 pub enum IndexType {
373     U16,
374     U32,
375 }
376 
377 /// Error creating an instance of a backend on the platform that
378 /// doesn't support this backend.
379 #[derive(Clone, Debug, PartialEq)]
380 pub struct UnsupportedBackend;
381 
382 /// An instantiated backend.
383 ///
384 /// Any startup the backend needs to perform will be done when creating the type that implements
385 /// `Instance`.
386 ///
387 /// # Examples
388 ///
389 /// ```rust
390 /// # extern crate gfx_backend_empty;
391 /// # extern crate gfx_hal;
392 /// use gfx_backend_empty as backend;
393 /// use gfx_hal as hal;
394 ///
395 /// // Create a concrete instance of our backend (this is backend-dependent and may be more
396 /// // complicated for some backends).
397 /// let instance = backend::Instance;
398 /// // We can get a list of the available adapters, which are either physical graphics
399 /// // devices, or virtual adapters. Because we are using the dummy `empty` backend,
400 /// // there will be nothing in this list.
401 /// for (idx, adapter) in hal::Instance::enumerate_adapters(&instance).iter().enumerate() {
402 ///     println!("Adapter {}: {:?}", idx, adapter.info);
403 /// }
404 /// ```
405 pub trait Instance<B: Backend>: Any + Send + Sync + Sized {
406     /// Create a new instance.
create(name: &str, version: u32) -> Result<Self, UnsupportedBackend>407     fn create(name: &str, version: u32) -> Result<Self, UnsupportedBackend>;
408     /// Return all available adapters.
enumerate_adapters(&self) -> Vec<adapter::Adapter<B>>409     fn enumerate_adapters(&self) -> Vec<adapter::Adapter<B>>;
410     /// Create a new surface.
create_surface( &self, _: &impl raw_window_handle::HasRawWindowHandle, ) -> Result<B::Surface, window::InitError>411     unsafe fn create_surface(
412         &self,
413         _: &impl raw_window_handle::HasRawWindowHandle,
414     ) -> Result<B::Surface, window::InitError>;
415     /// Destroy a surface.
416     ///
417     /// The surface shouldn't be destroyed before the attached
418     /// swapchain is destroyed.
destroy_surface(&self, surface: B::Surface)419     unsafe fn destroy_surface(&self, surface: B::Surface);
420 }
421 
422 /// A strongly-typed index to a particular `MemoryType`.
423 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
424 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
425 pub struct MemoryTypeId(pub usize);
426 
427 impl From<usize> for MemoryTypeId {
from(id: usize) -> Self428     fn from(id: usize) -> Self {
429         MemoryTypeId(id)
430     }
431 }
432 
433 struct PseudoVec<T>(Option<T>);
434 
435 impl<T> std::iter::Extend<T> for PseudoVec<T> {
extend<I: IntoIterator<Item = T>>(&mut self, iter: I)436     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
437         let mut iter = iter.into_iter();
438         self.0 = iter.next();
439         assert!(iter.next().is_none());
440     }
441 }
442 
443 /// The `Backend` trait wraps together all the types needed
444 /// for a graphics backend. Each backend module, such as OpenGL
445 /// or Metal, will implement this trait with its own concrete types.
446 #[allow(missing_docs)]
447 pub trait Backend: 'static + Sized + Eq + Clone + Hash + fmt::Debug + Any + Send + Sync {
448     type Instance: Instance<Self>;
449     type PhysicalDevice: adapter::PhysicalDevice<Self>;
450     type Device: device::Device<Self>;
451 
452     type Surface: window::PresentationSurface<Self>;
453     type Swapchain: window::Swapchain<Self>;
454 
455     type QueueFamily: queue::QueueFamily;
456     type CommandQueue: queue::CommandQueue<Self>;
457     type CommandBuffer: command::CommandBuffer<Self>;
458 
459     type ShaderModule: fmt::Debug + Any + Send + Sync;
460     type RenderPass: fmt::Debug + Any + Send + Sync;
461     type Framebuffer: fmt::Debug + Any + Send + Sync;
462 
463     type Memory: fmt::Debug + Any + Send + Sync;
464     type CommandPool: pool::CommandPool<Self>;
465 
466     type Buffer: fmt::Debug + Any + Send + Sync;
467     type BufferView: fmt::Debug + Any + Send + Sync;
468     type Image: fmt::Debug + Any + Send + Sync;
469     type ImageView: fmt::Debug + Any + Send + Sync;
470     type Sampler: fmt::Debug + Any + Send + Sync;
471 
472     type ComputePipeline: fmt::Debug + Any + Send + Sync;
473     type GraphicsPipeline: fmt::Debug + Any + Send + Sync;
474     type PipelineCache: fmt::Debug + Any + Send + Sync;
475     type PipelineLayout: fmt::Debug + Any + Send + Sync;
476     type DescriptorPool: pso::DescriptorPool<Self>;
477     type DescriptorSet: fmt::Debug + Any + Send + Sync;
478     type DescriptorSetLayout: fmt::Debug + Any + Send + Sync;
479 
480     type Fence: fmt::Debug + Any + Send + Sync;
481     type Semaphore: fmt::Debug + Any + Send + Sync;
482     type Event: fmt::Debug + Any + Send + Sync;
483     type QueryPool: fmt::Debug + Any + Send + Sync;
484 }
485