1#![allow(
2 unstable_name_collisions,
3 clippy::field_reassign_with_default,
4 clippy::double_must_use,
5 clippy::type_complexity,
6 clippy::missing_errors_doc,
7 clippy::too_many_arguments,
8 clippy::manual_clamp,
9 clippy::module_inception,
10 clippy::empty_line_after_doc_comments,
11 clippy::let_and_return,
12 clippy::missing_safety_doc
13)]
14#![deny(unsafe_code)]
15#![deny(missing_docs)]
16
17mod allocation;
20mod async_dispatch;
21mod backend_impl;
22pub mod buffer;
23mod capabilities;
24mod descriptor_mapping;
25mod device_buffer;
26pub mod emit;
27pub mod engine;
28mod executable_api;
29pub mod ext;
30pub mod megakernel;
31mod numeric;
32mod padded_upload;
33#[cfg(feature = "parity-testing")]
34mod parity_probe;
35pub mod pipeline;
36mod resident_dispatch;
37mod resident_download;
38mod resident_resource;
39mod resident_upload;
40pub mod runtime;
41pub mod spirv_backend;
42mod staging_reserve;
43mod stats;
44mod thread_pool;
45mod wait_backoff;
46
47pub use device_buffer::{WgpuDeviceBuffer, WGPU_BACKEND_ID};
48pub use executable_api::WgpuIR;
49pub use stats::WgpuBackendStats;
50use std::hash::BuildHasherDefault;
51use std::sync::{atomic::AtomicBool, Arc};
52use vyre_driver::shape_prediction::{ShapeFingerprint, ShapeHistory};
53use vyre_driver::DispatchConfig;
54use vyre_foundation::ir::DataType;
55use vyre_foundation::ir::Program;
56use vyre_foundation::validate::BackendValidationCapabilities;
57
58#[derive(Clone, Debug)]
59pub(crate) enum AdapterRecoveryTarget {
60 Index(usize),
61 Identity(crate::runtime::device::AdapterIdentity),
62}
63
64#[derive(Clone, Debug)]
66pub struct WgpuBackend {
67 pub(crate) adapter_info: wgpu::AdapterInfo,
68 pub(crate) adapter_name: Arc<str>,
69 pub(crate) device_limits: wgpu::Limits,
70 pub(crate) device_queue: Arc<arc_swap::ArcSwap<(wgpu::Device, wgpu::Queue)>>,
71 pub(crate) dispatch_arena: Arc<arc_swap::ArcSwap<DispatchArena>>,
72 pub(crate) persistent_pool: Arc<arc_swap::ArcSwap<crate::buffer::BufferPool>>,
73 pub(crate) pipeline_cache: Arc<runtime::cache::pipeline::LruPipelineCache>,
74 pub(crate) wgsl_dispatch_pipeline_cache: Arc<
75 dashmap::DashMap<
76 [u8; 32],
77 Arc<wgpu::ComputePipeline>,
78 BuildHasherDefault<rustc_hash::FxHasher>,
79 >,
80 >,
81 pub(crate) resident_pipeline_cache: Arc<
82 dashmap::DashMap<
83 (u64, u64, usize),
84 Arc<crate::pipeline::WgpuPipeline>,
85 BuildHasherDefault<rustc_hash::FxHasher>,
86 >,
87 >,
88 pub(crate) validation_cache: Arc<vyre_driver::validation::ValidationCache>,
89 pub(crate) shape_history: Arc<std::sync::Mutex<ShapeHistory>>,
90 pub(crate) predicted_programs: Arc<
91 dashmap::DashMap<
92 ShapeFingerprint,
93 PredictedProgram,
94 BuildHasherDefault<rustc_hash::FxHasher>,
95 >,
96 >,
97 pub(crate) bind_group_layout_cache: Arc<
98 dashmap::DashMap<
99 vyre_driver::BackendLayoutFingerprint,
100 Arc<[Arc<wgpu::BindGroupLayout>]>,
101 BuildHasherDefault<rustc_hash::FxHasher>,
102 >,
103 >,
104 pub(crate) resident_handles: Arc<
110 dashmap::DashMap<
111 vyre_driver::ResidentHandle,
112 crate::buffer::GpuBufferHandle,
113 BuildHasherDefault<rustc_hash::FxHasher>,
114 >,
115 >,
116 pub(crate) device_lost: Arc<AtomicBool>,
117 pub(crate) enabled_features: crate::runtime::device::EnabledFeatures,
118 pub(crate) recovery_target: AdapterRecoveryTarget,
119}
120
121#[derive(Clone, Debug)]
122pub(crate) struct PredictedProgram {
123 pub(crate) program: Arc<Program>,
124 pub(crate) config: DispatchConfig,
125}
126
127#[derive(Clone)]
129pub struct DispatchArena {
130 pool: crate::buffer::BufferPool,
131 readback_rings: Arc<runtime::readback_ring::ReadbackRingSet>,
132}
133
134impl std::fmt::Debug for DispatchArena {
135 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 formatter.write_str("DispatchArena { pool: size-classed }")
137 }
138}
139
140impl DispatchArena {
141 #[must_use]
143 #[inline]
144 pub fn new(device: wgpu::Device, queue: wgpu::Queue, config: &DispatchConfig) -> Self {
145 Self {
146 pool: crate::buffer::BufferPool::new(device, queue, config),
147 readback_rings: Arc::new(runtime::readback_ring::ReadbackRingSet::new()),
148 }
149 }
150
151 pub(crate) fn pool(&self) -> &crate::buffer::BufferPool {
152 &self.pool
153 }
154
155 pub(crate) fn readback_rings(&self) -> &Arc<runtime::readback_ring::ReadbackRingSet> {
156 &self.readback_rings
157 }
158}
159
160impl BackendValidationCapabilities for WgpuBackend {
161 fn backend_name(&self) -> &'static str {
162 "wgpu"
163 }
164
165 fn supports_cast_target(&self, target: &DataType) -> bool {
166 matches!(
167 target,
168 DataType::Bool
169 | DataType::U8
170 | DataType::U16
171 | DataType::U32
172 | DataType::U64
173 | DataType::I8
174 | DataType::I16
175 | DataType::I32
176 | DataType::I64
184 | DataType::F32
185 | DataType::Vec2U32
186 | DataType::Vec4U32
187 )
188 }
189
190 fn supports_subgroup_ops(&self) -> bool {
191 self.device_profile().supports_subgroup_ops
192 }
193
194 fn supports_indirect_dispatch(&self) -> bool {
195 self.device_profile().supports_indirect_dispatch
196 }
197
198 fn supports_specialization_constants(&self) -> bool {
199 self.device_profile().supports_specialization_constants
200 }
201
202 fn supports_distributed_collectives(&self) -> bool {
203 self.device_profile().supports_distributed_collectives
204 }
205}
206
207inventory::submit! {
208 vyre_driver::BackendRegistration {
209 id: "wgpu",
210 factory: || WgpuBackend::acquire().map(|backend| {
211 Box::new(backend) as Box<dyn vyre_driver::VyreBackend>
212 }),
213 supported_ops: vyre_driver::backend::validation::default_supported_ops_with_trap,
214 }
215}
216
217inventory::submit! {
218 vyre_driver::backend::BackendPrecedence {
219 id: "wgpu",
220 rank: 30,
221 }
222}
223
224inventory::submit! {
225 vyre_driver::backend::BackendCapability {
226 id: "wgpu",
227 dispatches: true,
228 }
229}
230
231impl vyre_driver::backend::private::Sealed for crate::pipeline::WgpuPipeline {}
232impl vyre_driver::backend::private::Sealed for WgpuBackend {}