cubecl_core/compute/
builder.rs1use alloc::{sync::Arc, vec::Vec};
2use derive_more::Deref;
3use pliron::r#type::TypeHandle;
4
5use crate::{KernelExpansion, KernelIntegrator, prelude::KernelDefinition};
6use alloc::collections::BTreeMap;
7use cubecl_ir::{
8 DeviceProperties, ElemType, Scope, TargetProperties,
9 metadata::{INFO_ALIGN, Info, Metadata, SizedInfoField},
10 pliron::value::Value,
11 settings::KernelSettings,
12};
13use cubecl_runtime::config::{CubeClRuntimeConfig, RuntimeConfig};
14
15#[derive(Deref)]
17pub struct KernelBuilder {
18 #[deref]
20 pub scope: Scope,
21 scalars: BTreeMap<ElemType, usize>,
22 buffer_idx: usize,
23 ext_meta_idx: usize,
24 settings: KernelSettings,
25}
26
27impl KernelBuilder {
28 pub fn scalar(&mut self, storage: ElemType) -> usize {
30 let current_id = self.scalars.entry(storage).or_default();
31 let id = *current_id;
32 *current_id += 1;
33 id
34 }
35
36 fn inc_buffer_id(&mut self) -> usize {
37 let id = self.buffer_idx;
38 self.buffer_idx += 1;
39 id
40 }
41
42 fn inc_ext_meta_id(&mut self) -> usize {
43 let id = self.ext_meta_idx;
44 self.ext_meta_idx += 1;
45 id
46 }
47
48 pub fn buffer(&mut self, value_ty: TypeHandle) -> Value {
50 let id = self.inc_buffer_id();
51 self.scope.global(id, None, value_ty)
52 }
53
54 pub fn peer_buffer(&mut self, value_ty: TypeHandle) -> Value {
57 let id = self.inc_buffer_id();
58 self.scope.peer_global(id, value_ty)
59 }
60
61 pub fn tensor(&mut self, value_ty: TypeHandle) -> Value {
63 let id = self.inc_buffer_id();
64 let ext_id = self.inc_ext_meta_id();
65 self.scope.global(id, Some(ext_id), value_ty)
66 }
67
68 pub fn tensor_map(&mut self) -> Value {
70 let id = self.inc_buffer_id();
71 let ext_id = self.inc_ext_meta_id();
72 self.scope.tensor_map(id, ext_id)
73 }
74
75 pub fn inplace(&mut self, position: usize) -> Value {
77 self.scope.kernel_arg(position)
78 }
79
80 pub fn runtime_properties(&mut self, properties: TargetProperties) {
81 self.scope.state_mut().target_properties = properties;
82 }
83
84 pub fn device_properties(&mut self, properties: Arc<DeviceProperties>) {
85 self.scope.device_properties(properties);
86 }
87
88 pub fn build(self) -> KernelDefinition {
90 for warning in self.scope.pop_warnings() {
91 log::warn!("[{}] {warning}", self.settings.kernel_name);
92 }
93 if let Some(debug) = self.scope.debug_state() {
94 debug.finish();
95 }
96 let info = self.create_info();
97 KernelIntegrator::new(KernelExpansion {
98 scope: self.scope,
99 info,
100 })
101 .integrate(self.settings)
102 }
103
104 fn create_info(&self) -> Info {
105 let address_type = self.settings.address_type;
106 let metadata = Metadata::new(self.buffer_idx, self.ext_meta_idx);
107 let mut scalar_fields = Vec::with_capacity(self.scalars.len());
108 let mut sized_meta = None;
109
110 let mut offset = 0;
111
112 for (&ty, &count) in self.scalars.iter() {
113 scalar_fields.push(SizedInfoField { ty, count, offset });
114 offset += (ty.expand_size(address_type) * count).next_multiple_of(INFO_ALIGN);
115 }
116
117 if metadata.static_len() > 0 {
118 let size = metadata.static_len();
119 sized_meta = Some(SizedInfoField {
120 ty: address_type.unsigned_type(),
121 count: size,
122 offset,
123 });
124 offset += (address_type.size() * size).next_multiple_of(INFO_ALIGN);
125 }
126
127 Info {
128 scalars: scalar_fields,
129 sized_meta,
130 has_dynamic_meta: metadata.num_extended_meta() > 0,
131 dynamic_meta_offset: offset,
132 metadata,
133 }
134 }
135
136 pub fn new(mut settings: KernelSettings) -> Self {
137 settings.debug_info = CubeClRuntimeConfig::get()
138 .compilation
139 .resolve_debug_info(settings.debug_info);
140
141 Self {
142 scope: Scope::root(settings.clone()),
143 scalars: Default::default(),
144 settings,
145 buffer_idx: 0,
146 ext_meta_idx: 0,
147 }
148 }
149}