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;
28pub mod ext;
29mod materializer;
30mod numeric;
31mod padded_upload;
32#[cfg(feature = "parity-testing")]
33mod parity_probe;
34pub mod pipeline;
35mod resident_dispatch;
36mod resident_download;
37mod resident_resource;
38mod resident_upload;
39pub mod runtime;
40pub mod spirv_backend;
41mod staging_reserve;
42mod stats;
43mod target_compiler;
44mod thread_pool;
45mod wait_backoff;
46
47pub use device_buffer::{WgpuDeviceBuffer, WGPU_BACKEND_ID};
48use vyre_foundation::operation::TargetId;
49pub const WGPU_TARGET_ID: TargetId = TargetId::expect_valid(WGPU_BACKEND_ID);
51pub use stats::WgpuBackendStats;
52use std::hash::BuildHasherDefault;
53use std::sync::{atomic::AtomicBool, Arc};
54use vyre_driver::shape_prediction::{ShapeFingerprint, ShapeHistory};
55use vyre_driver::DispatchConfig;
56use vyre_foundation::ir::DataType;
57use vyre_foundation::ir::Program;
58use vyre_foundation::validate::BackendValidationCapabilities;
59
60#[derive(Clone, Debug)]
61pub(crate) enum AdapterRecoveryTarget {
62 Index(usize),
63 Identity(crate::runtime::device::AdapterIdentity),
64}
65
66#[derive(Clone, Debug)]
68pub struct WgpuBackend {
69 pub(crate) adapter_info: wgpu::AdapterInfo,
70 pub(crate) adapter_name: Arc<str>,
71 pub(crate) device_limits: wgpu::Limits,
72 pub(crate) device_queue: Arc<arc_swap::ArcSwap<(wgpu::Device, wgpu::Queue)>>,
73 pub(crate) dispatch_arena: Arc<arc_swap::ArcSwap<DispatchArena>>,
74 pub(crate) persistent_pool: Arc<arc_swap::ArcSwap<crate::buffer::BufferPool>>,
75 pub(crate) pipeline_cache: Arc<runtime::cache::pipeline::LruPipelineCache>,
76 pub(crate) wgsl_dispatch_pipeline_cache: Arc<
77 dashmap::DashMap<
78 [u8; 32],
79 Arc<wgpu::ComputePipeline>,
80 BuildHasherDefault<rustc_hash::FxHasher>,
81 >,
82 >,
83 pub(crate) resident_pipeline_cache: Arc<
84 dashmap::DashMap<
85 (u64, u64, usize),
86 Arc<crate::pipeline::WgpuPipeline>,
87 BuildHasherDefault<rustc_hash::FxHasher>,
88 >,
89 >,
90 pub(crate) validation_cache: Arc<vyre_driver::validation::ValidationCache>,
91 pub(crate) shape_history: Arc<std::sync::Mutex<ShapeHistory>>,
92 pub(crate) predicted_programs: Arc<
93 dashmap::DashMap<
94 ShapeFingerprint,
95 PredictedProgram,
96 BuildHasherDefault<rustc_hash::FxHasher>,
97 >,
98 >,
99 pub(crate) bind_group_layout_cache: Arc<
100 dashmap::DashMap<
101 vyre_driver::BackendLayoutFingerprint,
102 Arc<[Arc<wgpu::BindGroupLayout>]>,
103 BuildHasherDefault<rustc_hash::FxHasher>,
104 >,
105 >,
106 pub(crate) resident_handles: Arc<
112 dashmap::DashMap<
113 vyre_driver::ResidentHandle,
114 crate::buffer::GpuBufferHandle,
115 BuildHasherDefault<rustc_hash::FxHasher>,
116 >,
117 >,
118 pub(crate) device_lost: Arc<AtomicBool>,
119 pub(crate) enabled_features: crate::runtime::device::EnabledFeatures,
120 pub(crate) recovery_target: AdapterRecoveryTarget,
121}
122
123#[derive(Clone, Debug)]
124pub(crate) struct PredictedProgram {
125 pub(crate) program: Arc<Program>,
126 pub(crate) config: DispatchConfig,
127}
128
129#[derive(Clone)]
131pub struct DispatchArena {
132 pool: crate::buffer::BufferPool,
133 readback_rings: Arc<runtime::readback_ring::ReadbackRingSet>,
134}
135
136impl std::fmt::Debug for DispatchArena {
137 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 formatter.write_str("DispatchArena { pool: size-classed }")
139 }
140}
141
142impl DispatchArena {
143 #[must_use]
145 #[inline]
146 pub fn new(device: wgpu::Device, queue: wgpu::Queue, config: &DispatchConfig) -> Self {
147 Self {
148 pool: crate::buffer::BufferPool::new(device, queue, config),
149 readback_rings: Arc::new(runtime::readback_ring::ReadbackRingSet::new()),
150 }
151 }
152
153 pub(crate) fn pool(&self) -> &crate::buffer::BufferPool {
154 &self.pool
155 }
156
157 pub(crate) fn readback_rings(&self) -> &Arc<runtime::readback_ring::ReadbackRingSet> {
158 &self.readback_rings
159 }
160}
161
162impl BackendValidationCapabilities for WgpuBackend {
163 fn backend_name(&self) -> &'static str {
164 "wgpu"
165 }
166
167 fn supports_cast_target(&self, target: &DataType) -> bool {
168 matches!(
169 target,
170 DataType::Bool
171 | DataType::U8
172 | DataType::U16
173 | DataType::U32
174 | DataType::U64
175 | DataType::I8
176 | DataType::I16
177 | DataType::I32
178 | DataType::I64
186 | DataType::F32
187 | DataType::Vec2U32
188 | DataType::Vec4U32
189 )
190 }
191
192 fn supports_subgroup_ops(&self) -> bool {
193 self.device_profile().supports_subgroup_ops
194 }
195
196 fn supports_indirect_dispatch(&self) -> bool {
197 self.device_profile().supports_indirect_dispatch
198 }
199
200 fn supports_specialization_constants(&self) -> bool {
201 self.device_profile().supports_specialization_constants
202 }
203
204 fn supports_distributed_collectives(&self) -> bool {
205 self.device_profile().supports_distributed_collectives
206 }
207}
208
209pub fn artifact_materializer(
211 backend: WgpuBackend,
212) -> Result<Box<dyn vyre_driver::ArtifactMaterializer>, vyre_driver::BackendError> {
213 materializer::materializer_for_backend(backend)
214}
215
216inventory::submit! {
217 vyre_driver::BackendRegistration {
218 id: WGPU_BACKEND_ID,
219 target_id: WGPU_TARGET_ID,
220 payload_format: Some(target_compiler::WGPU_TARGET_FORMAT),
221 reference_oracle: false,
222 factory: || WgpuBackend::acquire().map(|backend| {
223 Box::new(backend) as Box<dyn vyre_driver::VyreBackend>
224 }),
225 supported_ops: vyre_driver::backend::validation::default_supported_ops_with_trap,
226 semantic_operations: vyre_driver::backend::dialect_only_supported_ops,
227 target_compiler: Some(target_compiler::target_compiler_factory),
228 materializer: Some(materializer::materializer_factory),
229 }
230}
231
232inventory::submit! {
233 vyre_driver::backend::BackendPrecedence {
234 id: "wgpu",
235 rank: 30,
236 }
237}
238
239inventory::submit! {
240 vyre_driver::backend::BackendCapability {
241 id: "wgpu",
242 dispatches: true,
243 }
244}
245
246impl vyre_driver::backend::private::Sealed for crate::pipeline::WgpuPipeline {}
247impl vyre_driver::backend::private::Sealed for WgpuBackend {}