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 tensor(&mut self, value_ty: TypeHandle) -> Value {
56 let id = self.inc_buffer_id();
57 let ext_id = self.inc_ext_meta_id();
58 self.scope.global(id, Some(ext_id), value_ty)
59 }
60
61 pub fn tensor_map(&mut self) -> Value {
63 let id = self.inc_buffer_id();
64 let ext_id = self.inc_ext_meta_id();
65 self.scope.tensor_map(id, ext_id)
66 }
67
68 pub fn inplace(&mut self, position: usize) -> Value {
70 self.scope.kernel_arg(position)
71 }
72
73 pub fn runtime_properties(&mut self, properties: TargetProperties) {
74 self.scope.state_mut().target_properties = properties;
75 }
76
77 pub fn device_properties(&mut self, properties: Arc<DeviceProperties>) {
78 self.scope.device_properties(properties);
79 }
80
81 pub fn build(self) -> KernelDefinition {
83 for warning in self.scope.pop_warnings() {
84 log::warn!("[{}] {warning}", self.settings.kernel_name);
85 }
86 if let Some(debug) = self.scope.debug_state() {
87 debug.finish();
88 }
89 let info = self.create_info();
90 KernelIntegrator::new(KernelExpansion {
91 scope: self.scope,
92 info,
93 })
94 .integrate(self.settings)
95 }
96
97 fn create_info(&self) -> Info {
98 let address_type = self.settings.address_type;
99 let metadata = Metadata::new(self.buffer_idx, self.ext_meta_idx);
100 let mut scalar_fields = Vec::with_capacity(self.scalars.len());
101 let mut sized_meta = None;
102
103 let mut offset = 0;
104
105 for (&ty, &count) in self.scalars.iter() {
106 scalar_fields.push(SizedInfoField { ty, count, offset });
107 offset += (ty.expand_size(address_type) * count).next_multiple_of(INFO_ALIGN);
108 }
109
110 if metadata.static_len() > 0 {
111 let size = metadata.static_len();
112 sized_meta = Some(SizedInfoField {
113 ty: address_type.unsigned_type(),
114 count: size,
115 offset,
116 });
117 offset += (address_type.size() * size).next_multiple_of(INFO_ALIGN);
118 }
119
120 Info {
121 scalars: scalar_fields,
122 sized_meta,
123 has_dynamic_meta: metadata.num_extended_meta() > 0,
124 dynamic_meta_offset: offset,
125 metadata,
126 }
127 }
128
129 pub fn new(mut settings: KernelSettings) -> Self {
130 settings.debug_info = CubeClRuntimeConfig::get()
131 .compilation
132 .resolve_debug_info(settings.debug_info);
133
134 Self {
135 scope: Scope::root(settings.clone()),
136 scalars: Default::default(),
137 settings,
138 buffer_idx: 0,
139 ext_meta_idx: 0,
140 }
141 }
142}