1use crate::env;
15use crate::op::OpKind;
16
17pub mod splat_common;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
21pub enum KernelDispatchPolicy {
22 #[default]
24 PreferNative,
25 ForceCommon,
27 ForceNative,
29}
30
31impl KernelDispatchPolicy {
32 pub fn from_env() -> Self {
33 let v = env::var("KERNEL_DISPATCH").or_else(|| env::var("RLX_KERNEL_DISPATCH"));
34 match v.as_deref() {
35 Some("common") | Some("force_common") | Some("ForceCommon") => Self::ForceCommon,
36 Some("native") | Some("force_native") | Some("ForceNative") => Self::ForceNative,
37 _ => Self::PreferNative,
38 }
39 }
40}
41
42#[derive(Debug, Clone, Copy)]
44pub struct LogicalKernelEntry {
45 pub kind: OpKind,
46 pub name: &'static str,
48}
49
50pub fn registered_logical_kernels() -> &'static [LogicalKernelEntry] {
52 &[
53 LogicalKernelEntry {
54 kind: OpKind::GroupNorm,
55 name: "group_norm",
56 },
57 LogicalKernelEntry {
58 kind: OpKind::BatchNormInference,
59 name: "batch_norm_inference",
60 },
61 LogicalKernelEntry {
62 kind: OpKind::ResizeNearest2x,
63 name: "resize_nearest_2x",
64 },
65 LogicalKernelEntry {
66 kind: OpKind::GaussianSplatRender,
67 name: "gaussian_splat_render",
68 },
69 LogicalKernelEntry {
70 kind: OpKind::GaussianSplatRenderBackward,
71 name: "gaussian_splat_render_backward",
72 },
73 ]
74}
75
76#[derive(Debug, Clone, Copy, Default)]
78pub struct KernelDispatchConfig {
79 pub policy: KernelDispatchPolicy,
80 pub force_common_kinds: &'static [OpKind],
82 pub force_native_kinds: &'static [OpKind],
84}
85
86impl KernelDispatchConfig {
87 pub fn new(policy: KernelDispatchPolicy) -> Self {
88 Self {
89 policy,
90 ..Self::default()
91 }
92 }
93
94 pub fn from_env() -> Self {
95 Self::new(KernelDispatchPolicy::from_env())
96 }
97}
98
99pub fn should_lower_to_common(
101 kind: OpKind,
102 supported: &[OpKind],
103 config: KernelDispatchConfig,
104) -> bool {
105 if !registered_logical_kernels().iter().any(|e| e.kind == kind) {
106 return false;
107 }
108 if config.force_native_kinds.contains(&kind) {
109 return false;
110 }
111 if config.force_common_kinds.contains(&kind) {
112 return true;
113 }
114 match config.policy {
115 KernelDispatchPolicy::ForceCommon => true,
116 KernelDispatchPolicy::ForceNative => false,
117 KernelDispatchPolicy::PreferNative => !supported.is_empty() && !supported.contains(&kind),
118 }
119}
120
121pub fn logical_kinds_in_graph(
123 graph: &crate::Graph,
124 supported: &[OpKind],
125 config: KernelDispatchConfig,
126) -> Vec<OpKind> {
127 let mut kinds = Vec::new();
128 for node in graph.nodes() {
129 let k = node.op.kind();
130 if should_lower_to_common(k, supported, config) && !kinds.contains(&k) {
131 kinds.push(k);
132 }
133 }
134 kinds
135}