vyre_driver/backend/
artifact_lifecycle.rs1use std::collections::BTreeMap;
2
3use vyre_megakernel::{
4 Artifact, ArtifactValueId, Digest, TargetPayload, TargetPayloadFormat, TargetProfile,
5};
6
7use super::BackendError;
8
9#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub struct DeviceIdentity {
12 pub backend: &'static str,
14 pub device: String,
16 pub generation: u64,
18}
19
20pub trait Device: Send + Sync {
22 fn identity(&self) -> &DeviceIdentity;
24 fn target_format(&self) -> &TargetPayloadFormat;
26 fn target_profile(&self) -> &TargetProfile;
28 fn is_healthy(&self) -> bool;
30}
31
32#[derive(Clone, Debug, PartialEq, Eq)]
34pub enum BoundResource {
35 Host(Vec<u8>),
37 Resident(super::Resource),
39}
40
41#[derive(Clone, Debug, PartialEq, Eq)]
43pub struct BindingSet {
44 artifact: Digest,
45 resources: BTreeMap<ArtifactValueId, BoundResource>,
46 invocation_grid: Option<[u32; 3]>,
47}
48
49impl BindingSet {
50 #[must_use]
52 pub const fn new(artifact: Digest) -> Self {
53 Self {
54 artifact,
55 resources: BTreeMap::new(),
56 invocation_grid: None,
57 }
58 }
59
60 #[must_use]
62 pub const fn artifact(&self) -> Digest {
63 self.artifact
64 }
65
66 pub fn insert(&mut self, value: ArtifactValueId, resource: BoundResource) {
68 self.resources.insert(value, resource);
69 }
70
71 #[must_use]
73 pub const fn resources(&self) -> &BTreeMap<ArtifactValueId, BoundResource> {
74 &self.resources
75 }
76
77 pub fn set_invocation_grid(&mut self, grid: [u32; 3]) -> Result<(), BackendError> {
79 if let Some(axis) = grid.iter().position(|extent| *extent == 0) {
80 return Err(BackendError::InvalidProgram {
81 fix: format!(
82 "Fix: invocation grid axis {axis} must be positive, got {}.",
83 grid[axis]
84 ),
85 });
86 }
87 self.invocation_grid = Some(grid);
88 Ok(())
89 }
90
91 #[must_use]
93 pub const fn invocation_grid(&self) -> Option<[u32; 3]> {
94 self.invocation_grid
95 }
96}
97
98#[derive(Clone, Debug, PartialEq, Eq)]
100pub struct Completion {
101 pub artifact: Digest,
103 pub outputs: BTreeMap<ArtifactValueId, Vec<u8>>,
105 pub retained: BTreeMap<ArtifactValueId, Vec<u8>>,
107 pub device_ns: Option<u64>,
109}
110
111pub trait Submission: Send + Sync {
113 fn is_ready(&self) -> bool;
115 fn wait(self: Box<Self>) -> Result<Completion, BackendError>;
117}
118
119pub trait ArtifactInstance: Send + Sync {
121 fn artifact(&self) -> Digest;
123 fn payload(&self) -> Digest;
125 fn device(&self) -> &DeviceIdentity;
127 fn submit(&self, bindings: BindingSet) -> Result<Box<dyn Submission>, BackendError>;
129}
130
131pub trait ArtifactMaterializer: Send + Sync {
133 fn device(&self) -> &dyn Device;
135
136 fn allocate_resident(&self, _byte_len: usize) -> Result<super::Resource, BackendError> {
138 Err(BackendError::UnsupportedFeature {
139 name: "artifact resident buffer allocation".to_string(),
140 backend: self.device().identity().backend.to_string(),
141 })
142 }
143
144 fn upload_resident(
146 &self,
147 _resource: &super::Resource,
148 _bytes: &[u8],
149 ) -> Result<(), BackendError> {
150 Err(BackendError::UnsupportedFeature {
151 name: "artifact resident buffer upload".to_string(),
152 backend: self.device().identity().backend.to_string(),
153 })
154 }
155
156 fn upload_resident_at(
158 &self,
159 resource: &super::Resource,
160 offset_bytes: usize,
161 bytes: &[u8],
162 ) -> Result<(), BackendError> {
163 if offset_bytes == 0 {
164 return self.upload_resident(resource, bytes);
165 }
166 Err(BackendError::UnsupportedFeature {
167 name: "artifact resident ranged upload".to_string(),
168 backend: self.device().identity().backend.to_string(),
169 })
170 }
171
172 fn free_resident(&self, _resource: super::Resource) -> Result<(), BackendError> {
174 Err(BackendError::UnsupportedFeature {
175 name: "artifact resident buffer free".to_string(),
176 backend: self.device().identity().backend.to_string(),
177 })
178 }
179
180 fn materialize(
182 &self,
183 artifact: &Artifact,
184 payload: &TargetPayload,
185 ) -> Result<Box<dyn ArtifactInstance>, BackendError>;
186}