use cubecl_core::server::{LaunchError, ResourceLimitError, ServerError};
use cubecl_core::{self as cubecl, prelude::*};
use cubecl_server::runtime::Runtime;
type R = crate::MetalRuntime;
#[cube(launch)]
fn oversized_smem_kernel(output: &mut [u32], #[comptime] shared_size: usize) {
let mut shared = Shared::new_slice(shared_size);
let idx = output[0] as usize;
shared[idx] = output[0];
sync_cube();
output[0] = shared[idx + 1];
}
#[test]
fn oversized_shared_memory_is_a_resource_limit_error() {
let client = R::client(&Default::default());
let max = client.properties().hardware.max_shared_memory_size;
let shared_size = (max + 1).div_ceil(size_of::<u32>());
let requested_bytes = shared_size * size_of::<u32>();
let handle = client.create_from_slice(u32::as_bytes(&[0]));
oversized_smem_kernel::launch(
&client,
CubeCount::Static(1, 1, 1),
CubeDim::new_1d(1),
unsafe { BufferArg::from_raw_parts(handle.clone(), 1) },
shared_size,
);
client
.flush()
.expect("a launch failure is not the flush's to report");
let err = client
.read_one(handle)
.expect_err("the launch never wrote the buffer, so the read fails on it");
let ServerError::Unwritten { root, .. } = err else {
panic!("expected the read to fail on the unwritten buffer, got: {err}");
};
match *root {
ServerError::Launch(LaunchError::TooManyResources(ResourceLimitError::SharedMemory {
requested,
max: reported_max,
..
})) => {
assert_eq!(requested, requested_bytes);
assert_eq!(reported_max, max);
}
other => panic!("expected a shared memory resource limit error, got: {other}"),
}
}