Skip to main content

ferrum_interfaces/vnext/execution/
allocation.rs

1use super::{
2    invalid_plan, quantize_storage_bytes, AllocationKind, AllocationLifetime, BufferRequest,
3    BufferUsage, Deserialize, DynamicStorageContract, ElementType, ResourceId, Serialize,
4    VNextError,
5};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct ResourceAllocation {
9    pub(super) resource_id: ResourceId,
10    pub(super) per_instance_bytes: u64,
11    pub(super) instance_stride_bytes: u64,
12    pub(super) instance_count: u32,
13    pub(super) size_bytes: u64,
14    pub(super) alignment_bytes: u64,
15    pub(super) usage: BufferUsage,
16    pub(super) element_type: ElementType,
17    pub(super) lifetime: AllocationLifetime,
18    pub(super) kind: AllocationKind,
19    pub(super) storage: DynamicStorageContract,
20}
21
22impl ResourceAllocation {
23    pub(super) fn new(
24        resource_id: ResourceId,
25        per_instance_bytes: u64,
26        alignment_bytes: u64,
27        usage: BufferUsage,
28        element_type: ElementType,
29        kind: AllocationKind,
30        storage: DynamicStorageContract,
31    ) -> Result<Self, VNextError> {
32        if per_instance_bytes == 0 || alignment_bytes == 0 || !alignment_bytes.is_power_of_two() {
33            return Err(invalid_plan(format!(
34                "resource `{resource_id}` has invalid size or alignment"
35            )));
36        }
37        let instance_stride_bytes =
38            quantize_storage_bytes(per_instance_bytes, alignment_bytes, storage.profile())?;
39        Ok(Self {
40            resource_id,
41            per_instance_bytes,
42            instance_stride_bytes,
43            instance_count: 1,
44            size_bytes: instance_stride_bytes,
45            alignment_bytes,
46            usage,
47            element_type,
48            lifetime: AllocationLifetime::Plan,
49            kind,
50            storage,
51        })
52    }
53
54    pub fn resource_id(&self) -> &ResourceId {
55        &self.resource_id
56    }
57
58    pub const fn size_bytes(&self) -> u64 {
59        self.size_bytes
60    }
61
62    pub const fn per_instance_bytes(&self) -> u64 {
63        self.per_instance_bytes
64    }
65
66    pub const fn instance_stride_bytes(&self) -> u64 {
67        self.instance_stride_bytes
68    }
69
70    pub const fn instance_count(&self) -> u32 {
71        self.instance_count
72    }
73
74    pub fn scoped_offset_bytes(
75        &self,
76        base_offset_bytes: u64,
77        _active_sequence_slot: u32,
78    ) -> Result<u64, VNextError> {
79        if base_offset_bytes >= self.per_instance_bytes {
80            return Err(invalid_plan(format!(
81                "resource `{}` base offset is outside its per-instance span",
82                self.resource_id
83            )));
84        }
85        Ok(base_offset_bytes)
86    }
87
88    pub const fn alignment_bytes(&self) -> u64 {
89        self.alignment_bytes
90    }
91
92    pub const fn usage(&self) -> BufferUsage {
93        self.usage
94    }
95
96    pub const fn element_type(&self) -> ElementType {
97        self.element_type
98    }
99
100    pub const fn lifetime(&self) -> AllocationLifetime {
101        self.lifetime
102    }
103
104    pub fn kind(&self) -> &AllocationKind {
105        &self.kind
106    }
107
108    pub fn storage(&self) -> &DynamicStorageContract {
109        &self.storage
110    }
111
112    pub fn buffer_request(&self) -> Result<BufferRequest, VNextError> {
113        BufferRequest::new(
114            self.resource_id.clone(),
115            self.size_bytes,
116            self.alignment_bytes,
117            self.usage,
118            self.element_type,
119        )
120    }
121}